26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
53 #pragma package(smart_init)
72 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
73 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
74 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
75 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
76 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
77 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
88 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
89 AnsiString(TrainModeIn));
136 for(
int x = 0; x < 4; x++)
145 for(
int x = 0; x < 4; x++)
154 for(
int x = 0; x < 4; x++)
159 for(
int x = 0; x < 4; x++)
163 for(
int x = 0; x < 3; x++)
201 for(
int x = 0; x < 4; x++)
260 throw Exception(
"Error in attempting to delete FrontCodePtr");
264 for(
int x = 0; x < 4; x++)
268 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
273 for(
int x = 0; x < 4; x++)
277 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
306 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
372 bool TempDerail =
false;
418 else if((NextElementPosition > -1) && (NextEntryPos > -1))
489 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
499 for(
int x = 0; x < 4; x++)
506 for(
int x = 0; x < 4; x++)
767 int LockedVectorNumber;
897 AnsiString ReasonArray[24] = {
"a driver is awaited",
"a guard is awaited",
"of a medical emergency",
"of a technical problem",
"of a security issue",
898 "of a safety issue",
"of a disturbance",
"a train crew member has been taken ill",
"the driver has been taken ill",
"the guard has been taken ill",
899 "a report has been received concerning safety",
"a shoe has been lost under the train",
"of a reported theft",
900 "of an incident involving an animal",
"some luggage has been lost under the train",
"a minor repair is needed",
"a suspicious object has to be dealt with safely",
901 "a door is stuck open",
"additional stock has to be attached",
"a security alert",
"of a train fault",
"of an operating incident",
"safety checks are required",
902 "of a shortage of on train crew"};
909 if(DwellTime < TDateTime(30.0 / 86400))
911 DwellTime = TDateTime(30.0 / 86400);
913 int randval = random(10000);
918 if(randval < Utilities->MinorDelayCutoff)
925 if(randval < Utilities->ModerateDelayCutoff)
932 if(randval < Utilities->MajorDelayCutoff)
947 if(
NewDelay <
double(DwellTime) * 1440)
953 NewDelay -= double(DwellTime) * 1440;
1014 int randval2 = rand() % 24;
1015 AnsiString Reason = ReasonArray[randval2];
1018 " minutes because " + Reason);
1020 " minutes because " + Reason);
1026 " minutes because of a minor problem");
1028 " minutes because of a minor problem");
1180 if(BufferLocation ==
"")
1185 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1247 int NextElementPosition, NextEntryPos;
1271 NextElementPosition = -1;
1274 if((NextElementPosition > -1) && (NextEntryPos > -1))
1411 AnsiString StationName;
1422 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1436 if((NextElementPosition > -1) && (NextEntryPos > -1))
1570 if(TIFEntryPos == 0)
1607 if(NextElementPosition > -1)
1644 AnsiString Loc =
"";
1645 bool LocNamed =
false;
1674 Loc =
"outside railway";
1706 NextElementPosition = -1;
1717 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1735 if((NextElementPosition > -1) && (NextEntryPos > -1))
1773 FirstPair.second).
GetELink() == TempELink))
1778 SecondPair.second).
GetELink() == TempELink))
1792 FirstPair.second).
GetELink() == TempELink))
1797 SecondPair.second).
GetELink() == TempELink))
1811 FirstPair.second).
GetELink() == TempELink))
1816 SecondPair.second).
GetELink() == TempELink))
1846 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1849 int NewLastElement = 0, NewLastExitPos = 0;
1867 if(NewLastElement == -1)
1873 if(NewLastExitPos == -1)
1877 LastElement = NewLastElement;
1878 LastExitPos = NewLastExitPos;
1881 if(CumDistance < 1200)
1887 int FirstDistance = 0;
1888 if(CumDistance >= 1200)
1890 FirstDistance = 100;
1894 FirstDistance = 1200 - CumDistance;
1896 if(FirstDistance < 100)
1898 FirstDistance = 100;
1924 if(VectorIT->RouteNumber == RouteNumber)
1961 " failed when changing aspect.\nTrains can only pass under signaller control.");
1995 LockedVectorNumber)))
2154 for(
int x = 0; x < 4; x++)
2161 for(
int x = 0; x < 4; x++)
2187 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
2192 if(OtherTrainEntryPos == -1)
2194 throw Exception(
"Error - OtherTrainEntryPos not set");
2213 int OtherTrainID = -1;
2214 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2305 bool StopRequired =
false;
2320 int NextElementEntryPos = -1;
2321 int NextElementExitPos = -1;
2322 bool TrainOnNextElement =
false;
2323 bool StopSignalAtNextElement =
false;
2324 if(ForwardConnection)
2332 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2334 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || TrainAtStopLinkPos3 || TrainAtStopLinkPos4 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2390 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2603 if(Code.Length() != 4)
2607 for(
int x = 1; x < 5; x++)
2614 for(
int x = 0; x < 4; x++)
2777 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2790 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2805 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2814 TRect SourceRect, DestRect;
2816 DestRect.init(0, 0, 8, 8);
2819 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2821 TempGraphic->PixelFormat = pf8bit;
2822 TempGraphic->Width = 16;
2823 TempGraphic->Height = 16;
2829 TempGraphic->Transparent =
true;
2833 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2834 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2840 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2848 else if(TempElement.
SpeedTag == 89)
2852 else if(TempElement.
SpeedTag == 90)
2856 else if(TempElement.
SpeedTag == 91)
2860 else if(TempElement.
SpeedTag == 92)
2864 else if(TempElement.
SpeedTag == 93)
2868 else if(TempElement.
SpeedTag == 94)
2872 else if(TempElement.
SpeedTag == 95)
2876 TempGraphic->Transparent =
true;
2880 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2881 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2883 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2890 for(
int x = 0; x < 40; x++)
2905 TempGraphic->Transparent =
true;
2909 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2910 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2912 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2926 TempGraphic->Transparent =
true;
2930 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2931 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2935 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2938 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2943 TempGraphic->Transparent =
true;
2947 int BDVectorPos = -1;
2956 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2961 TempGraphic->Transparent =
true;
2965 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2966 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2968 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2974 TempGraphic->Transparent =
true;
2978 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2979 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2981 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3247 throw Exception(
"Error, same train on two different bridge tracks");
3293 AnsiString(EntryPos) +
"," +
HeadCode);
3310 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3329 AnsiString(EntryPos) +
"," +
HeadCode);
3338 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3371 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3372 int LockedVectorNumber;
3385 TRect SourceRect, DestRect;
3386 DestRect.init(0, 0, 8, 8);
3393 int FirstELink, SecondELink = -1;
3396 if(RoutePair2.first > -1)
3405 if(SecondELink == -1)
3407 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3412 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3422 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3423 DestGraphic->PixelFormat = pf8bit;
3424 DestGraphic->Width = 8;
3425 DestGraphic->Height = 8;
3426 DestGraphic->Transparent =
true;
3429 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3438 PrefDirElement, LockedVectorNumber))
3453 if(ElementEntryPos > 1)
3475 AnsiString(EntryPos) +
"," +
HeadCode);
3477 bool WrongRoute =
false;
3503 int LinkNumber = TrackElement.
Link[EntryPos];
3504 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3509 bool LogActionErrorCalled =
false;
3519 LogActionErrorCalled =
true;
3536 else if(LinkNumber == 3)
3544 LogActionErrorCalled =
true;
3561 else if(LinkNumber == 7)
3569 LogActionErrorCalled =
true;
3586 else if(LinkNumber == 9)
3594 LogActionErrorCalled =
true;
3626 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3631 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3641 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3646 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3655 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3676 bool ColourError =
false, ColourError2 =
false;
3681 ColourError2 =
true;
3683 for(
int x = 0; x < 4; x++)
3688 ColourError2 =
true;
3694 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3698 for(
int x = 0; x < 4; x++)
3785 AnsiString(EntryPos) +
"," +
HeadCode);
3786 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3787 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3788 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3789 TrainInFrontInSignallerModeFlag =
false;
3790 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3791 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3792 bool SignallerStopRequired =
false;
3806 if(CurrentTrackVectorPosition > -1)
3810 if((EntryPos == 0) || (EntryPos == 2))
3823 else if(EntryPos == 1)
3847 EntryHalfLength = CurrentElementHalfLength;
3852 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3856 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3904 FrontElementMaxSpeed = LimitingSpeed;
3940 double ExitSpeedAtMaxBraking;
3945 ExitSpeedAtMaxBraking = 0;
3955 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3957 SpeedToUse = ExitSpeedAtMaxBraking;
3961 SpeedToUse = LimitingSpeed;
3976 RedSignalFlag =
false;
3977 BuffersFlag =
false;
3978 StationFlag =
false;
3979 BuffersOrContinuationNowFlag =
false;
3980 ContinuationNextFlag =
false;
3983 CumulativeLength += (2 * CurrentElementHalfLength);
3986 SignallerStopRequired =
true;
4008 bool StopRequired =
false;
4024 StationFlag =
false;
4030 BuffersOrContinuationNowFlag =
true;
4032 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
4036 if((EntryPos == 0) || (EntryPos == 2))
4058 if(NextTrackVectorPosition > -1)
4063 if((NextEntryPos == 0) || (NextEntryPos == 2))
4076 else if(NextEntryPos == 1)
4089 if(NextEntryPos > 1)
4103 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
4115 RedSignalFlag =
true;
4136 TrainInFrontInSignallerModeFlag =
true;
4161 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
4173 double MaxHalfSpeed;
4177 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
4179 MaxHalfSpeed = FrontElementMaxSpeed;
4183 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
4191 bool HalfSpeedLimited =
false;
4195 HalfSpeedLimited =
true;
4225 if(HalfSpeedLimited)
4250 if(SignallerStopRequired)
4266 int TempMaxExitSpeed;
4269 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4271 MaxExitSpeedAtHalfBraking = 0;
4275 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4279 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4281 TempMaxExitSpeed = FrontElementMaxSpeed;
4285 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4297 if(ExitSpeedHalfSquared < 10)
4307 if(ExitSpeedFullSquared < 10)
4379 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4380 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4404 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4405 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4415 if(!BuffersOrContinuationNowFlag)
4417 if(NextSpeedLimit < LimitingSpeed)
4419 LimitingSpeed = NextSpeedLimit;
4423 int TempMaxExitSpeed;
4427 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4429 MaxExitSpeedAtHalfBraking = 0;
4433 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4435 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4437 TempMaxExitSpeed = FrontElementMaxSpeed;
4441 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4452 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4465 if(!BuffersOrContinuationNowFlag)
4467 CurrentTrackVectorPosition = NextTrackVectorPosition;
4468 EntryPos = NextEntryPos;
4469 CurrentElementHalfLength = NextElementHalfLength;
4472 ContinuationNextFlag =
true;
4476 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4496 if(ExitSpeedHalfSquared < 10)
4506 if(ExitSpeedFullSquared < 10)
4569 double DeltaExitTimeToMaxInSecs;
4570 double DistanceToMax;
4579 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4581 DistanceToMax = EntryHalfLength;
4584 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4585 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4602 double DeltaExitTimeToMaxInSecs;
4603 double DistanceToMax;
4612 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4614 DistanceToMax = EntryHalfLength / 2;
4617 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4618 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4629 if(ExitSpeedHalfSquared < 10)
4639 if(ExitSpeedFullSquared < 10)
4658 if((EntryPos == 0) || (EntryPos == 2))
4680 if(NextTrackVectorPosition > -1)
4682 int NextElementLength;
4683 if(NextEntryPos > 1)
4691 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4887 int ElementCount = 0;
4895 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4953 if((EntryPos == 0) || (EntryPos == 2))
4975 CurrentTrackVectorPosition = NextTrackVectorPosition;
4976 EntryPos = NextEntryPos;
4978 if(ElementCount > 1000)
5006 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
5031 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
5032 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
5033 int RouteStartPosition;
5035 int PlatformPosition;
5037 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
5053 if(Distance > (4000 + LeadElementDistance))
5076 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
5079 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
5125 if(!PlatformFoundFlag)
5127 PlatformPosition = CurrentTrackVectorPosition;
5130 PlatformFoundFlag =
true;
5146 if((EntryPos == 0) || (EntryPos == 2))
5190 if(ElementNumber < 2)
5192 SkipRouteCheck =
true;
5196 SkipRouteCheck =
false;
5198 if(ElementNumber == 1)
5200 RouteStartPosition = CurrentTrackVectorPosition;
5210 if(ElementNumber > 1)
5214 RouteOrPartRouteSet =
true;
5218 RouteOrPartRouteSet =
false;
5221 if(!SkipRouteCheck && !RouteOrPartRouteSet)
5228 int ExitLink = CurrentTrackElement.
Link[ExitPos];
5229 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5241 Distance += CurrentTrackElement.
Length01;
5245 Distance += CurrentTrackElement.
Length23;
5247 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5248 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5249 CurrentTrackVectorPosition = NextTrackVectorPosition;
5250 EntryPos = NextEntryPos;
5287 return(RepeatHeadCode);
5309 bool FrontValid =
false, RearValid =
false;
5310 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5314 TrainToBeJoinedBy = NULL;
5328 int TrainToBeJoinedByID = -1;
5349 if((TrainToBeJoinedByID < 0) && RearValid)
5368 if(TrainToBeJoinedByID < 0)
5370 TrainToBeJoinedBy = NULL;
5375 if(!TrainToBeJoinedBy->
Stopped())
5377 TrainToBeJoinedBy = NULL;
5387 void TTrain::LogAction(
int Caller, AnsiString OwnHeadCode, AnsiString OtherHeadCode,
TActionType ActionType, AnsiString LocationName, AnsiString SplitDistribution,
5388 TDateTime TimetableNonRepeatTime,
bool Warning)
5424 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5425 AnsiString BaseLog =
"", WarningBaseLog =
"", ReminderBaseLog =
"", PerfLog =
"", ActionLog =
"";
5426 int IntMinsLate = 0;
5427 bool TTEvent =
false;
5432 ActionLog =
" arrived at ";
5442 ActionLog =
" terminated at ";
5448 ActionLog =
" departed from ";
5451 if(ActionType ==
Pass)
5453 ActionLog =
" passed ";
5458 ActionLog =
" created at ";
5460 if(ActionType ==
Enter)
5462 ActionLog =
" entered railway at ";
5466 ActionLog =
" changed its description to '" +
Description +
"' at ";
5469 if(ActionType ==
Leave)
5471 ActionLog =
" left railway at ";
5476 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from front to ";
5481 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from rear to ";
5486 ActionLog =
" joined by ";
5491 ActionLog =
" changed direction at ";
5496 ActionLog =
" became new service ";
5501 ActionLog =
" taken under signaller control at ";
5505 ActionLog =
" restored to timetable control at ";
5511 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5515 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5519 ActionLog =
" REMOVED FROM RAILWAY at ";
5524 ActionLog =
" received signaller authority to proceed";
5528 ActionLog =
" received signaller authority to step forward";
5532 ActionLog =
" changed direction under signaller control at ";
5536 ActionLog =
" received signaller authority to pass stop signal";
5540 ActionLog =
" received signaller instruction to stop";
5544 ActionLog =
" stopped on signaller instruction ";
5548 ActionLog =
" joined under signaller control by ";
5552 ActionLog =
" suffered an onboard power failure at ";
5556 ActionLog =
" failure repaired at ";
5560 ActionLog =
" left railway under signaller control at ";
5562 if(OtherHeadCode !=
"")
5564 OtherHeadCode +=
" at ";
5596 bool TimePerformance =
true;
5604 TimePerformance =
false;
5608 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5610 if(ActionType ==
Pass)
5624 IntMinsLate = int(ceil(MinsLate));
5628 IntMinsLate = int(floor(MinsLate));
5630 if(IntMinsLate == 0)
5632 PerfLog =
" on time";
5634 else if(IntMinsLate == 1)
5636 PerfLog =
" 1 minute late";
5638 else if(IntMinsLate == -1)
5640 PerfLog =
" 1 minute early";
5642 else if(IntMinsLate > 1)
5644 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5646 else if(IntMinsLate < -1)
5648 int PosIntMinsLate = -IntMinsLate;
5649 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5651 if(LocationName.Pos(
'-') > 0)
5653 PerfLog =
"," + PerfLog;
5666 if(ReminderBaseLog !=
"")
5671 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5675 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5680 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5686 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5690 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5695 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5701 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5705 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5710 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5716 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5720 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5739 AnsiString LocName =
"";
5810 if(LocationName ==
"")
5814 int RearTrainRearPos, RearTrainFrontPos, RearTrainExitPos;
5815 int FrontTrainRearPos, FrontTrainFrontPos;
5818 if(LocationName ==
"")
5820 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5824 bool TemporaryDelay =
false;
5826 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
5850 AnsiString SplittingTrainDescription =
Description;
5857 for(
int x = 0; x < 4; x++)
5877 double NewTrainPowerAtRail;
5883 NewTrainMass =
Mass * double(MassPercent)/100.0;
5885 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
5886 if(NewTrainPowerAtRail == 0)
5888 NewTrainPowerAtRail = 0.08;
5896 NewTrainMass =
Mass;
5924 if(!SplitTrainExplicitDescription)
5969 if(LocationName ==
"")
5973 int RearTrainRearPos, RearTrainFrontPos;
5974 int FrontTrainRearPos, FrontTrainFrontPos, FrontTrainExitPos;
5977 if(LocationName ==
"")
5979 throw Exception(
"Error - LocationName not set in RearTrainSplit");
5983 bool TemporaryDelay =
false;
5985 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
6009 AnsiString SplittingTrainDescription =
Description;
6016 for(
int x = 0; x < 4; x++)
6036 double NewTrainPowerAtRail;
6042 NewTrainMass =
Mass * double(MassPercent)/100.0;
6044 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
6045 if(NewTrainPowerAtRail == 0)
6047 NewTrainPowerAtRail = 0.08;
6055 NewTrainMass =
Mass;
6083 if(!SplitTrainExplicitDescription)
6174 TTrain *TrainToBeJoinedBy;
6207 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6209 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6273 int RouteNumber = -1;
6278 int CorrectRouteID = OR.
RouteID;
6284 bool FirstPass =
true;
6289 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6423 for(
int x = 0; x < IncNum; x++)
6456 else if(Ptr->
Command ==
"jbo")
6461 else if(Ptr->
Command ==
"dsc")
6472 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6478 bool IncludeFER =
false;
6486 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6491 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6502 else if(Ptr->
Command ==
"Fjo")
6508 else if(Ptr->
Command ==
"Frh")
6518 else if(Ptr->
Command ==
"Frh-sh")
6569 else if(Ptr->
Command ==
"jbo")
6574 else if(Ptr->
Command ==
"dsc")
6579 else if(Ptr->
Command ==
"cdt")
6587 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
7009 int RouteNumber = -1;
7014 int CorrectRouteID = OR.
RouteID;
7020 bool FirstPass =
true;
7025 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
7053 ",FloatingLabelNextString" +
"," +
HeadCode);
7054 AnsiString RetStr =
"", LocationName =
"";
7057 if(ActionTime == TDateTime(-1))
7061 if(ActionTime == TDateTime(-1))
7067 if(ActionTime != TDateTime(-1))
7075 throw Exception(
"Error - start entry in FloatingLabelNextString");
7119 else if(Ptr->
Command ==
"Fns")
7125 else if(Ptr->
Command ==
"F-nshs")
7156 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7158 else if(Ptr->
Command ==
"Frh")
7160 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7162 else if(Ptr->
Command ==
"Fer")
7164 AnsiString AllowedExits =
"";
7167 else if(Ptr->
Command ==
"Fjo")
7172 else if(Ptr->
Command ==
"jbo")
7177 else if(Ptr->
Command ==
"fsp")
7182 else if(Ptr->
Command ==
"rsp")
7187 else if(Ptr->
Command ==
"cdt")
7191 else if(Ptr->
Command ==
"dsc")
7200 throw Exception(
"Error - start entry in FloatingLabelNextString where TTClockTime > ActionTime");
7244 else if(Ptr->
Command ==
"Fns")
7250 else if(Ptr->
Command ==
"F-nshs")
7281 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7283 else if(Ptr->
Command ==
"Frh")
7285 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7287 else if(Ptr->
Command ==
"Fer")
7289 AnsiString AllowedExits =
"";
7292 else if(Ptr->
Command ==
"Fjo")
7297 else if(Ptr->
Command ==
"jbo")
7302 else if(Ptr->
Command ==
"fsp")
7307 else if(Ptr->
Command ==
"rsp")
7312 else if(Ptr->
Command ==
"cdt")
7316 else if(Ptr->
Command ==
"dsc")
7325 throw Exception(
"Error - start entry in FloatingLabelNextString in final 'else'");
7369 else if(Ptr->
Command ==
"Fns")
7375 else if(Ptr->
Command ==
"F-nshs")
7406 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7408 else if(Ptr->
Command ==
"Frh")
7410 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7412 else if(Ptr->
Command ==
"Fer")
7414 AnsiString AllowedExits =
"";
7417 else if(Ptr->
Command ==
"Fjo")
7422 else if(Ptr->
Command ==
"jbo")
7427 else if(Ptr->
Command ==
"fsp")
7432 else if(Ptr->
Command ==
"rsp")
7437 else if(Ptr->
Command ==
"cdt")
7441 else if(Ptr->
Command ==
"dsc")
7585 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
7586 AnsiString DepTime =
"", EventTime =
"";
7587 bool CDTFlag =
false;
7589 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
7590 AnsiString TowardsLocation =
"";
7593 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
7595 TowardsLocation = AVI->LocationName;
7597 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
7606 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
7613 if(AVI->Command ==
"cdt")
7618 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
7633 RetStr +=
"\nNew service splits at approx. " + EventTime;
7637 if(AVI->Command ==
"jbo")
7656 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
7671 RetStr +=
"\nNew service finishes and forms another new service at approx. " + EventTime;
7675 if(AVI->Command ==
"Fjo")
7694 if(AVI->Command ==
"Frh")
7696 RetStr +=
"\nNew service finishes and remains at the location.";
7700 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7707 if(TowardsLocation !=
"")
7709 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
7713 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7718 if(TowardsLocation !=
"")
7720 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
7724 RetStr +=
"\nNew service departs at " + DepTime;
7733 if(TowardsLocation !=
"")
7735 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
7739 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
7744 if(TowardsLocation !=
"")
7746 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
7750 RetStr +=
"\nNew service departs at approx. " + DepTime;
7767 if(TowardsLocation !=
"")
7769 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
7773 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
7778 if(TowardsLocation !=
"")
7780 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
7784 RetStr +=
"\nNew service departs at approx. " + DepTime;
7803 ",FloatingTimetableString" +
"," +
HeadCode);
7804 AnsiString RetStr =
"", PartStr =
"";
7806 bool SkipDep =
false, SkipDepActedOn =
false;
7812 throw Exception(
"Error - start entry in FloatingTimetableString");
7815 bool FirstPass =
true;
7828 AnsiString TrainLoc =
"";
7874 AnsiString TrainLoc =
"";
7914 else if(Ptr->
Command ==
"Fns")
7920 else if(Ptr->
Command ==
"F-nshs")
7953 else if(Ptr->
Command ==
"Frh")
7957 else if(Ptr->
Command ==
"Fer")
7959 AnsiString AllowedExits =
"";
7962 else if(Ptr->
Command ==
"Fjo")
7967 else if(Ptr->
Command ==
"jbo")
7972 else if(Ptr->
Command ==
"fsp")
7982 PartStr+=
", split mass%-Power% = 50-50";
7985 else if(Ptr->
Command ==
"rsp")
7995 PartStr+=
", split mass%-Power% = 50-50";
7998 else if(Ptr->
Command ==
"cdt")
8002 else if(Ptr->
Command ==
"dsc")
8008 RetStr = RetStr +
'\n' + PartStr;
8022 SkipDepActedOn =
true;
8033 RetStr =
"Timetable finished";
8037 RetStr =
"No timetable";
8041 return(
"Timetable:\n" + RetStr);
8194 bool ForwardHeadCode;
8198 ForwardHeadCode =
true;
8203 ForwardHeadCode =
false;
8346 if(ColourNumber == 0)
8350 else if(ColourNumber == 1)
8354 else if(ColourNumber == 2)
8358 else if(ColourNumber == 3)
8362 else if(ColourNumber == 4)
8366 else if(ColourNumber == 5)
8370 else if(ColourNumber == 6)
8374 else if(ColourNumber == 7)
8378 else if(ColourNumber == 8)
8382 else if(ColourNumber == 9)
8386 else if(ColourNumber == 10)
8390 else if(ColourNumber == 11)
8394 else if(ColourNumber == 12)
8398 else if(ColourNumber == 13)
8402 else if(ColourNumber == 14)
8414 for(
int x = 0; x < 4; x++)
8421 for(
int x = 0; x < 4; x++)
8506 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
8509 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
8510 bool GiveMessagesFalse =
false;
8511 bool CheckLocationsExistInRailwayTrue =
true;
8518 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
8521 if(Marker[6] ==
'1')
8986 bool HideFlashingTrain =
true;
8989 Graphics::TBitmap *SmallTrainBitmap;
9030 HideFlashingTrain =
false;
9035 HideFlashingTrain =
false;
9040 HideFlashingTrain =
false;
9045 HideFlashingTrain =
false;
9050 HideFlashingTrain =
false;
9054 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
9058 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
9082 for(
int y = 0; y < 3; y++)
9086 bool FoundFlag =
false;
9097 if(IMPair.first != IMPair.second)
9124 if((LocationName ==
"") && (
MidElement > -1))
9128 if((LocationName ==
"") && (
LagElement > -1))
9132 if(LocationName ==
"")
9134 throw Exception(
"Error - Location name not set in TrainAtLocation");
9145 for(
int x = 0; x < 4; x++)
9157 for(
int x = 0; x < 4; x++)
9174 AnsiString(LinkNumber) +
"," +
HeadCode);
9226 int DistanceToRedSignal = 0, DistanceToExit = -1;
9227 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
9231 float MinsEarly = 0;
9232 TDateTime DepartureTime;
9233 TDateTime ArrivalTime;
9261 if(TempTTE < LastTimeToExit)
9296 if(TempTTE < LastTimeToExit)
9319 if(TempTTE < LastTimeToExit)
9349 if(TempTTE < LastTimeToExit)
9372 if(TempTTE < LastTimeToExit)
9415 float CurrentStopTime;
9416 float LaterStopTime;
9417 float RecoverableTime;
9425 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
9432 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
9433 bool DistanceToExitSet = (DistanceToExit > -1);
9434 int GenericDistance = DistanceToRedSignal;
9435 if(DistanceToExitSet)
9437 GenericDistance = DistanceToExit;
9453 float TimeToSubtract, TotalStopTime;
9456 TimeToSubtract = RecoverableTime;
9499 if(CurrentStopTime > 0)
9501 TotalStopTime = CurrentStopTime + LaterStopTime;
9510 else if((MinsEarly > 0) && !
Stopped())
9512 TotalStopTime = LaterStopTime + MinsEarly;
9516 if(LaterStopTime == 0)
9518 TotalStopTime = CurrentStopTime;
9524 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
9527 if(AvTrackSpeed < 30)
9531 int Speed = AvTrackSpeed;
9541 if(DistanceToRedSignalSet)
9543 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9553 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9582 if((NextEntryPos == 0) || (NextEntryPos == 2))
9709 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9751 int IncrementalMinutes = 0;
9752 int IncrementalDigits = 0;
9760 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
9796 if(AVEntry0.
Command ==
"Snt-sh")
9801 int IncrementalMinutes = 0;
9802 int IncrementalDigits = 0;
9810 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
9854 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9934 AnsiString Loc =
"";
9935 bool ElementFound =
false;
9940 ElementFound =
true;
9945 ElementFound =
true;
9950 ElementFound =
true;
9979 else if(AVEntryPtr->
Command ==
"Fer")
9981 bool CorrectExit =
false;
10093 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10111 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10126 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10137 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
10138 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
10139 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
10141 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
10142 "," + AnsiString(Mass) +
"," + ModeStr);
10144 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
10146 int RearExitPos = -1;
10148 for(
int x = 0; x < 4; x++)
10155 if(RearExitPos == -1)
10157 throw Exception(
"Error, RearExit == -1 in AddTrain");
10159 bool ReportFlag =
true;
10164 ReportFlag =
false;
10176 if(ModeStr ==
"Timetable")
10182 if(MaxRunningSpeed < 10)
10184 MaxRunningSpeed = 10;
10186 if(SignallerSpeed < 10)
10188 SignallerSpeed = 10;
10190 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
10191 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
10198 if(SignallerControl)
10228 if(!SignallerControl)
10243 if(!SignallerControl)
10254 AnsiString Loc =
"";
10271 if(!SignallerControl)
10290 int RouteNumber = -1;
10291 bool SignalsSet =
false;
10298 int RouteStartPosition;
10302 if(FirstPair.first == RouteNumber)
10304 RouteStartPosition = FirstPair.second;
10306 else if(SecondPair.first == RouteNumber)
10308 RouteStartPosition = SecondPair.second;
10312 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
10318 else if(RouteNumber > -1)
10338 int LinkedRouteNumber = -1;
10359 int RouteStartPosition;
10363 if(FirstPair.first == RouteNumber)
10365 RouteStartPosition = FirstPair.second;
10367 else if(SecondPair.first == RouteNumber)
10369 RouteStartPosition = SecondPair.second;
10373 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
10379 else if(RouteNumber > -1)
10399 int LinkedRouteNumber = -1;
10420 AnsiString(TrackVectorNumber));
10423 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10432 throw Exception(
"Error, VecPos not set in EntryPos");
10434 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
10439 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
10444 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
10458 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10466 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
10476 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10497 return(RepeatTime);
10506 AnsiString RetStr =
"", PartStr =
"";
10514 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
10522 if(Ptr->SignallerControl)
10524 RetStr =
"Train under signaller control";
10529 if(Ptr->ArrivalTime == Ptr->DepartureTime)
10540 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
10544 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
10548 else if(Ptr->FormatType ==
PassTime)
10552 else if(Ptr->Command ==
"Fns")
10558 else if(Ptr->Command ==
"F-nshs")
10561 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
10568 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10575 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10578 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
10581 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10588 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10590 PartStr =
"Terminate at " + Ptr->LocationName;
10592 else if(Ptr->Command ==
"Frh")
10594 PartStr =
"Terminate at " + Ptr->LocationName;
10596 else if(Ptr->Command ==
"Fer")
10598 AnsiString AllowedExits;
10602 else if(Ptr->Command ==
"Fjo")
10605 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10607 else if(Ptr->Command ==
"jbo")
10610 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10612 else if(Ptr->Command ==
"fsp")
10617 else if(Ptr->Command ==
"rsp")
10622 else if(Ptr->Command ==
"cdt")
10626 else if(Ptr->Command ==
"dsc")
10632 RetStr = RetStr +
'\n' + PartStr;
10640 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
10651 TTrainDataEntry *LinkedTrainDataPtr,
int IncrementalMinutes,
int IncrementalDigits, AnsiString RetStr)
10654 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
10655 AnsiString DepTime =
"", EventTime =
"";
10656 bool CDTFlag =
false;
10658 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
10659 AnsiString TowardsLocation =
"";
10662 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
10664 TowardsLocation = AVI->LocationName;
10666 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
10675 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
10681 if(AVI->Command ==
"cdt")
10683 CDTFlag = !CDTFlag;
10686 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
10689 RetStr +=
"\nNew service splits at " + EventTime;
10693 if(AVI->Command ==
"jbo")
10696 RetStr +=
"\nNew service joined by " +
GetRepeatHeadCode(70, AVI->OtherHeadCode, RptNum, IncrementalDigits) +
" at " + EventTime;
10700 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
10703 RetStr +=
"\nNew service finishes and forms another new service at " + EventTime;
10707 if(AVI->Command ==
"Fjo")
10710 RetStr +=
"\nNew service finishes and joins " +
TrainController->
GetRepeatHeadCode(71, AVI->OtherHeadCode, RptNum, IncrementalDigits) +
" at " + EventTime;
10714 if(AVI->Command ==
"Frh")
10716 RetStr +=
"\nNew service finishes and remains at location.";
10720 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
10725 if(TowardsLocation !=
"")
10727 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
10731 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
10736 if(TowardsLocation !=
"")
10738 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
10742 RetStr +=
"\nNew service departs at " + DepTime;
10907 ActiveTrackElementNameMapEntry.second = 0;
10913 std::ifstream TTBLFile(FileName, std::ios_base::binary);
10916 if(TTBLFile.is_open())
10918 char *TrainTimetableString =
new char[10000];
10920 bool EndOfFile =
false;
10923 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10925 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10932 delete[] TrainTimetableString;
10936 AnsiString OneLine(TrainTimetableString);
10937 bool FinalCallFalse =
false;
10938 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10942 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10943 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10948 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
10950 delete[] TrainTimetableString;
10954 OneLine = AnsiString(TrainTimetableString);
10960 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10962 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10972 OneLine = AnsiString(TrainTimetableString);
10974 if(OneLine.Length() > 9999)
10976 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
10978 delete[] TrainTimetableString;
10982 bool FinalCallFalse =
false;
10983 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10987 delete[] TrainTimetableString;
10991 if(EndOfFile && (Count < 2))
10994 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
10996 delete[] TrainTimetableString;
11002 delete[] TrainTimetableString;
11007 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
11018 bool CheckLocationsExistInRailway)
11146 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
11156 if(OneLine[1] !=
'*')
11158 int SCPos = OneLine.Pos(
';');
11169 bool AllCommas =
true;
11171 for(
int x = 1; x < OneLine.Length() + 1; x++)
11173 if(OneLine[x] !=
',')
11178 if(AllCommas || (OneLine ==
""))
11193 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
11194 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
11195 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
11196 TDateTime StartTime(0);
11198 bool Warning =
false;
11225 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
11226 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
11227 double MaxBrakeRate = 0;
11228 double PowerAtRail = 0;
11229 int SignallerSpeed = 0;
11230 if(OneLine[1] ==
'*')
11236 int Pos = OneLine.Pos(
',');
11239 int SubStringLength = 20;
11240 if(OneLine.Length() < 20)
11242 SubStringLength = OneLine.Length();
11244 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
11248 TrainInfoStr = OneLine.SubString(1, Pos - 1);
11249 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
11260 TempTrainDataEntry.
HeadCode = HeadCode;
11264 if(Description !=
"")
11269 TempTrainDataEntry.
Mass = Mass;
11277 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
11280 while(NewRemainder[NewRemainder.Length()] ==
',')
11282 if(NewRemainder.Length() > 1)
11284 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
11293 if(NewRemainder ==
"")
11295 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
11300 int CommaCount = 0;
11301 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
11303 if(NewRemainder[x] ==
',')
11308 if(CommaCount == 0)
11310 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
11312 int SubStringLength = 20;
11313 if(OneLine.Length() < 20)
11315 SubStringLength = OneLine.Length();
11318 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
11319 OneLine.SubString(1, SubStringLength) +
"'....");
11324 AnsiString OneEntry =
"";
11329 bool FinishFlag =
false;
11331 for(
int x = 0; x < CommaCount + 1; x++)
11333 if((CommaCount == 0) || (x < CommaCount))
11338 if(CommaCount == 0)
11340 OneEntry = NewRemainder;
11345 Pos = NewRemainder.Pos(
',');
11346 OneEntry = NewRemainder.SubString(1, Pos - 1);
11347 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
11353 RearStartOrRepeatMins = 0;
11354 FrontStartOrRepeatDigits = 0;
11355 NumberOfRepeats = 0;
11356 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11357 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11359 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11370 if(Warning && (Second ==
"Frh"))
11372 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
11376 if(Warning && (Second ==
"Fjo"))
11379 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
11416 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
11420 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
11422 if(NewRemainder[1] !=
'R')
11425 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
11431 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11435 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
11438 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
11444 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
11449 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11454 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
11457 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11473 TDateTime TempTime;
11479 ActionVectorEntry.
Warning = Warning;
11495 ActionVectorEntry.
Command = Second;
11510 else if(FormatType ==
TimeCmd)
11516 ActionVectorEntry.
Command = Second;
11524 ActionVectorEntry.
Command = Second;
11525 ActionVectorEntry.
ExitList = ExitList;
11533 ActionVectorEntry.
Command = Second;
11547 ActionVectorEntry.
Command = Second;
11558 ActionVectorEntry.
Command = Second;
11568 ActionVectorEntry.
Command = Second;
11570 if((Second ==
"fsp") || (Second ==
"rsp"))
11585 ActionVectorEntry.
Command = Second;
11594 ActionVectorEntry.
Command = Second;
11600 ActionVectorEntry.
Command = Second;
11608 ActionVectorEntry.
Command = Second;
11611 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11616 OneEntry = NewRemainder;
11621 RearStartOrRepeatMins = 0;
11622 FrontStartOrRepeatDigits = 0;
11623 NumberOfRepeats = 0;
11624 if((FinishFlag) && (OneEntry[1] !=
'R'))
11627 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
11631 if(OneEntry[1] !=
'R')
11633 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11634 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11636 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'.\nIf the program version is not the latest the "
11637 "timetable may have features that aren't compatible with the version in use.");
11654 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
11661 TDateTime TempTime;
11667 ActionVectorEntry.
Warning = Warning;
11674 ActionVectorEntry.
Command = Second;
11682 ActionVectorEntry.
Command = Second;
11691 ActionVectorEntry.
Command = Second;
11700 ActionVectorEntry.
Command = Second;
11710 ActionVectorEntry.
Command = Second;
11711 ActionVectorEntry.
ExitList = ExitList;
11715 ActionVectorEntry.
Command = Second;
11717 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11722 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
11738 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11757 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
11762 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
11777 if(TimeStr.Length() < 5)
11782 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
11787 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
11792 if(TimeStr[3] !=
':')
11797 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
11802 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
11807 while(TimeStr.Length() > 5)
11809 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
11811 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
11812 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
11814 if((WholeHours + FracHour) >= 95.98334)
11819 Time = TDateTime((WholeHours + FracHour) / 24);
11826 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
11827 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
11836 TDateTime TempTime;
11838 if(OneEntry.Length() > 0)
11840 if(OneEntry[1] ==
'W')
11843 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
11847 if(OneEntry ==
"Frh")
11857 if(OneEntry.Length() < 7)
11862 int Pos = OneEntry.Pos(
';');
11870 First = OneEntry.SubString(1, 5);
11876 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
11879 if((Remainder.Length() >= 3) && (Remainder[1] >=
'0') && (Remainder[1] <=
'9') && (Remainder[2] >=
'0') && (Remainder[2] <=
'9') && (Remainder[3] ==
':'))
11882 if(Remainder.Length() < 7)
11887 Pos = Remainder.Pos(
';');
11894 Second = Remainder.SubString(1, 5);
11900 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11913 Pos = Remainder.Pos(
';');
11916 Second = Remainder;
11917 if(Second ==
"cdt")
11942 if((Pos != 4) && (Pos != 7) && (Pos != 8))
11948 Second = Remainder.SubString(1, Pos - 1);
11950 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11952 Pos = Remainder.Pos(
';');
11959 Third = Remainder.SubString(1, Pos - 1);
11960 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11963 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11966 int SpacePos = Third.Pos(
' ');
11972 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
11973 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
11975 if(CheckLocationsExistInRailway)
11985 if(Second ==
"Snt")
12008 if(Second ==
"Sns-sh")
12027 if(Second ==
"F-nshs")
12041 if(Second ==
"Sns-fsh")
12055 if(Second ==
"Fns-sh")
12075 if(Second ==
"pas")
12090 if(Second ==
"Fer")
12097 if(CheckLocationsExistInRailway)
12108 if(Second ==
"dsc")
12110 if(Third.Length() > 60)
12112 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters in '" + Third +
"'");
12116 for(
int x = 1; x < Third.Length() + 1; x++)
12119 if((Third[x] <
' ') && (Third[x] >= 0))
12121 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + Third +
"'");
12137 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
12138 (Second !=
"Frh-sh"))
12150 if(Second ==
"Frh-sh")
12158 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
12162 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
12166 if((Second ==
"Sfs") || (Second ==
"Sns"))
12171 if((Fourth !=
"") && ((Second ==
"fsp") || (Second ==
"rsp")))
12188 bool ErrorFlag =
false;
12190 if((SplitDistributionString.Length() > 6 ) || (SplitDistributionString.Length() < 3))
12194 int pos = SplitDistributionString.Pos(
'-');
12201 AnsiString MassStr = SplitDistributionString.SubString(1, pos - 1);
12202 AnsiString PowerStr = SplitDistributionString.SubString(pos + 1, SplitDistributionString.Length() - pos);
12205 int x = MassStr.ToInt();
12206 int y = PowerStr.ToInt();
12207 if((x > 99) || (x < 1) || (y > 100) || (y < 0))
12212 catch(
const Exception &e)
12219 TimetableMessage(GiveMessages,
"Error in split distribution " + SplitDistributionString +
", should be 'AA-BB' where AA is the percentage mass (min 1, max 99) and BB the percentage " +
12220 "power for the new split-off train");
12241 if((LocStr.Length() >= 3) && (LocStr[1] >=
'0') && (LocStr[1] <=
'9') && (LocStr[2] >=
'0') && (LocStr[2] <=
'9') && (LocStr[3] ==
':'))
12246 for(
int x = 1; x < LocStr.Length() + 1; x++)
12248 if(((LocStr[x] <
' ') && (LocStr[x] >= 0)) || (LocStr[x] ==
',') || (LocStr[x] ==
';'))
12262 if(CheckLocationsExistInRailway)
12267 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
12268 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
12269 "that includes a continuation will not be valid.");
12287 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
12290 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
12295 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
12297 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
12299 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
12305 for(
int x = 3; x >= 0; x--)
12307 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
12308 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
12310 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
12326 AnsiString CurrentID =
"";
12328 if(IDSet.Length() == 0)
12330 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
12334 for(
int x = 1; x <= IDSet.Length(); x++)
12337 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
12339 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
12361 int Pos = IDSet.Pos(
' ');
12372 CurrentID = IDSet.SubString(1, Pos - 1);
12373 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
12385 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
12392 if(!ExitList.empty())
12394 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
12396 if(*ELIT == VecPos)
12398 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
12405 ExitList.push_back(VecPos);
12415 Pos = IDSet.Pos(
' ');
12422 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
12429 AnsiString Remainder =
"";
12430 int SemiColonCount = 0;
12432 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
12434 if(TrainInfoStr[x] ==
';')
12439 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
12441 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
12442 "'. Should be headcode + optional description for a continuing service;" +
12443 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
12447 if(SemiColonCount == 0)
12449 HeadCode = TrainInfoStr;
12458 if(SemiColonCount == 1)
12460 Pos = TrainInfoStr.Pos(
';');
12461 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12462 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12468 if(Description ==
"")
12470 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12474 if(Description.Length() > 60)
12476 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12480 for(
int x = 1; x < Description.Length() + 1; x++)
12483 if((Description[x] <
' ') && (Description[x] >= 0))
12485 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12494 Pos = TrainInfoStr.Pos(
';');
12495 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12496 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12502 Pos = Remainder.Pos(
';');
12503 Description = Remainder.SubString(1, Pos - 1);
12504 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12505 if(Description ==
"")
12507 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12511 if(Description.Length() > 60)
12513 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12517 for(
int x = 1; x < Description.Length() + 1; x++)
12520 if((Description[x] <
' ') && (Description[x] >= 0))
12522 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12527 Pos = Remainder.Pos(
';');
12528 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
12530 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12531 if(StartSpeedStr ==
"")
12533 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
12537 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
12539 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
12541 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
12546 StartSpeed = StartSpeedStr.ToInt();
12552 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12556 Pos = Remainder.Pos(
';');
12557 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
12559 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12560 if(MaxRunningSpeedStr ==
"")
12562 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
12566 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
12568 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
12570 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
12575 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
12581 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12585 if(MaxRunningSpeed < 10)
12588 MaxRunningSpeed = 10;
12591 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12595 Pos = Remainder.Pos(
';');
12596 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
12598 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12601 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
12605 for(
int x = 1; x < MassStr.Length() + 1; x++)
12607 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
12609 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
12614 Mass = MassStr.ToInt() * 1000;
12620 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
12626 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
12630 Pos = Remainder.Pos(
';');
12631 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
12633 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12634 if(MaxBrakeForceStr ==
"")
12636 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
12640 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
12642 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
12644 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
12649 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
12652 if((MaxBrakeForce / Mass) > 1)
12654 MaxBrakeForce = Mass;
12657 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
12661 if((MaxBrakeForce / Mass) < 0.01)
12663 MaxBrakeForce = Mass * 0.01;
12666 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
12671 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
12673 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
12675 if(SemiColonCount == 6)
12677 GrossPowerStr = Remainder;
12678 SignallerSpeedStr =
"30";
12682 Pos = Remainder.Pos(
';');
12683 GrossPowerStr = Remainder.SubString(1, Pos - 1);
12684 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12687 if(GrossPowerStr ==
"")
12689 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
12693 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
12695 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
12697 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
12703 double GrossPower = GrossPowerStr.ToInt() * 1000;
12710 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
12714 else if(GrossPower == 0)
12719 else if((GrossPower > 0) && (GrossPower < 10000))
12722 GrossPower = 10000;
12724 PowerAtRail = GrossPower * 0.8;
12728 if(SignallerSpeedStr ==
"")
12730 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
12734 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
12736 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
12738 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
12743 SignallerSpeed = SignallerSpeedStr.ToInt();
12749 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12753 if(SignallerSpeed < 10)
12756 SignallerSpeed = 10;
12759 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12777 if(OneEntry.Length() < 7)
12779 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12783 int SemiColonCount = 0;
12785 for(
int x = 1; x < OneEntry.Length() + 1; x++)
12787 if(OneEntry[x] ==
';')
12792 if(SemiColonCount != 3)
12794 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12798 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
12800 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12804 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
12809 Pos = Remainder.Pos(
';');
12810 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
12812 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12813 if(MinutesStr ==
"")
12815 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
12819 if(MinutesStr.Length() > 3)
12822 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
12826 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
12828 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
12830 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
12835 RearStartOrRepeatMins = MinutesStr.ToInt();
12836 if(RearStartOrRepeatMins == 0)
12838 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
12842 Pos = Remainder.Pos(
';');
12843 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
12845 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12846 if(DigitsStr ==
"")
12848 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
12852 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
12854 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
12856 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
12861 if(DigitsStr.Length() > 2)
12863 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
12867 FrontStartOrRepeatDigits = DigitsStr.ToInt();
12881 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
12885 AnsiString NumberStr = Remainder;
12887 if(NumberStr ==
"")
12889 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
12893 if(NumberStr.Length() > 4)
12896 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
12900 for(
int x = 1; x < NumberStr.Length() + 1; x++)
12902 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
12905 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
12910 NumberOfRepeats = NumberStr.ToInt();
12911 if(NumberOfRepeats == 0)
12913 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
13187 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
13208 TwoLocationFlag =
false;
13214 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
13228 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
13244 "Error in timetable - a signaller controlled service can have no more than one item (a repeat) after the start event, see: " +
13256 "Error in timetable - a signaller controlled service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
13282 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
13295 SecondPassMessage(GiveMessages,
"Error in timetable - only 'Frh' or 'Fjo' finish events are permitted immediately after "
13296 "an 'Sns' or 'Sfs' event for: " + TDEntry.
HeadCode +
". The program is unable to determine the "
13297 "location of any other type of finish.");
13303 if((AVEntry0.
Command ==
"Snt-sh") || (AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13309 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event can't immediately follow an 'Snt-sh', 'Sns-sh' or 'Sns-fsh' "
13310 "event for: " + TDEntry.
HeadCode);
13320 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13325 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
13335 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13340 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
13350 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13361 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
13371 SecondPassMessage(GiveMessages,
"Error in timetable - the event immediately before the repeat must be a finish for: " + TDEntry.
HeadCode);
13383 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13390 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
13399 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " + TDEntry.
HeadCode);
13418 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
13420 AnsiString LocationName =
"";
13434 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
13435 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13444 if(AVEntry0.
Command ==
"Snt-sh")
13458 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
13474 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh', 'Snt-fsh' or 'Sns-fsh' followed by an illegal event for: " +
13475 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13487 bool FoundFlag =
false;
13491 if((AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13493 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13505 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
13518 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13543 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13565 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13587 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13612 bool LocFoundFlag, FnsFoundFlag;
13616 LocFoundFlag =
false;
13617 FnsFoundFlag =
false;
13618 for(
int y =
TrainDataVector.at(x).ActionVector.size() - 1; y >= 0; y--)
13623 FnsFoundFlag =
true;
13632 LocFoundFlag =
true;
13643 SecondPassMessage(GiveMessages,
"Error in timetable - the program can't determine the location of an 'Fns' finish, it must be preceded "
13644 "by an event at the same location that has an identified location name, normally an arrival, see "
13651 if(FnsFoundFlag && !LocFoundFlag)
13653 SecondPassMessage(GiveMessages,
"Error in timetable - the program can't determine the location of an 'Fns' finish, it must be preceded "
13654 "by an event at the same location that has an identified location name, normally an arrival, see "
13668 if(AVEntry0.
Command ==
"Sns")
13680 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sns' event for: " + TDEntry.
HeadCode);
13688 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode +
13689 ". The event isn't valid for a stationary train.");
13697 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode);
13704 TDateTime SnsEventTime = AVEntry0.
EventTime;
13707 bool BreakFlag =
false;
13710 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13715 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SnsServiceRef)
13737 if(AVEntry0.
Command ==
"Sfs")
13739 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13747 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event must be followed by a departure and arrival before another split, see " +
TrainDataVector.at(x).ServiceReference);
13759 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13764 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13784 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13791 SecondPassMessage(GiveMessages,
"Error in timetable - an 'fsp' or 'rsp' event must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13806 if(AVEntry0.
Command ==
"Sfs")
13818 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sfs' event for: " + TDEntry.
HeadCode);
13826 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode +
13827 ". The event isn't valid for a stationary train.");
13835 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode);
13842 TDateTime SfsEventTime = AVEntry0.
EventTime;
13844 bool BreakFlag =
false;
13847 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13852 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SfsServiceRef)
13872 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13877 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13898 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13905 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"' must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13910 else if((AVEntry.
Command ==
"Sns") || (AVEntry.
Command ==
"Sfs"))
13913 "Please make sure that the finish event of the service that links to this event is preceded by an "
13914 "event at the same location that has an identified location name, normally an arrival.");
13919 else if(AVEntry.
Command ==
"Snt-sh")
13922 "Please make sure that the service starts with zero speed and is at a named location.");
13927 else if((AVEntry.
Command ==
"Sns-fsh") || (AVEntry.
Command ==
"Sns-sh"))
13930 "Please make sure that the event is followed (not necessarily immediately) by a departure.");
13937 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13950 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13960 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish event for: " + TDEntry.
HeadCode);
13967 if(AVEntry.
Command ==
"F-nshs")
13972 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
14000 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
14001 ". The event isn't valid for a stationary train.");
14011 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
14019 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
14020 ". The event isn't valid for a stationary train.");
14038 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
14039 ". The event isn't valid for a stationary train.");
14057 SecondPassMessage(GiveMessages,
"Error in timetable - a 'dsc' is followed by an illegal event for: " + TDEntry.
HeadCode +
14058 ". The event isn't valid for a stationary train.");
14068 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
14076 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
14077 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
14095 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
14096 ". The event isn't valid for a moving train.");
14118 bool LastEntryIsAnArrival =
false;
14125 LastEntryIsAnArrival =
false;
14126 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14133 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14135 if(LastEntryIsAnArrival)
14139 LastEntryIsAnArrival =
false;
14145 LastEntryIsAnArrival =
true;
14152 LastEntryIsAnArrival =
true;
14153 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14160 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14162 if(LastEntryIsAnArrival)
14166 LastEntryIsAnArrival =
false;
14172 LastEntryIsAnArrival =
true;
14182 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14190 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
14198 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
14199 ". The event isn't valid for a stationary train.");
14210 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
14218 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
14219 ". The event isn't valid for a moving train.");
14233 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14240 throw Exception(
"Timetable error, TimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14244 throw Exception(
"Timetable error, TimeLoc event has neither arrival nor departure time set for " + TDEntry.
HeadCode);
14251 throw Exception(
"Timetable error, TimeTimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14255 throw Exception(
"Timetable error, TimeTimeLoc event has either arrival or departure time not set for " + TDEntry.
HeadCode);
14264 throw Exception(
"Timetable error, Cmd or PassTime event has EventTime not set for " + TDEntry.
HeadCode);
14268 throw Exception(
"Timetable error, Cmd or PassTime event has either arrival or departure time set for " + TDEntry.
HeadCode);
14275 throw Exception(
"Timetable error, Repeat event has a time set for " + TDEntry.
HeadCode);
14286 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14301 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
14309 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
14324 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14336 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14348 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
14349 ", may be before timetable start time");
14360 AnsiString LastLocationName =
"";
14364 bool LastEntryIsAnArrival =
false;
14369 LastEntryIsAnArrival =
false;
14370 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14371 if(LastLocationName !=
"")
14373 throw Exception(
"Timetable error, moving Snt event has LocationName set for " + TDEntry.
HeadCode);
14375 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
14388 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14400 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14413 TwoLocationFlag =
true;
14418 LastEntryIsAnArrival =
false;
14422 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14425 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14430 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
14433 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
14439 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14445 LastEntryIsAnArrival =
true;
14446 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14447 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14459 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14471 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14484 TwoLocationFlag =
true;
14489 LastEntryIsAnArrival =
false;
14493 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14496 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14504 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
14511 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14519 AnsiString LocationNameToBeChecked =
"";
14524 unsigned int y = 0;
14538 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
14539 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
14557 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
14566 TwoLocationFlag =
true;
14577 if(TwoLocationFlag)
14587 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14592 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat event doesn't have a location name set for " + TDEntry.
HeadCode);
14594 AnsiString LocName =
"";
14600 throw Exception(
"Error, 'Snt' event at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
14607 throw Exception(
"Error, 'Snt' unlocated event has a location name set for " + TDEntry.
HeadCode);
14630 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14655 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14677 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14699 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14718 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14721 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
14736 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14741 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
14745 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
14749 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
14753 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
14792 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14794 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
14800 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
14813 int IncMinutes = 0;
14823 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14829 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
14835 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
14840 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
14846 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
14851 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
14864 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14890 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
14898 if(HeadCode.Length() > 4)
14900 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
14911 int ForwardCount = 0;
14912 int ReverseCount = 0;
14914 if(MainHeadCode == SecondHeadCode)
14916 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
14925 if(TDEntry.
HeadCode == MainHeadCode)
14927 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14942 if(ForwardCount == 0)
14945 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
14947 if(ForwardCount > 2)
14950 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
14951 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
14960 if(TDEntry.
HeadCode == SecondHeadCode)
14962 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14977 if(ReverseCount == 0)
14979 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
14984 if(ReverseCount > 2)
14987 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
14988 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
14993 if(ForwardCount != ReverseCount)
14995 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
14996 " than the other way round");
15027 int ForwardCount = 0;
15028 int ReverseCount = 0;
15029 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
15038 if(TDEntry.
HeadCode == MainHeadCode)
15040 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15043 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15048 ForwardEntryPtr = &AVEntry;
15050 ForwardTDVectorNumber = x;
15053 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
15054 (AVEntry.
Command ==
"Frh-sh")))
15059 ForwardEntryPtr = &AVEntry;
15061 ForwardTDVectorNumber = x;
15067 if(ForwardCount == 0)
15070 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
15072 if(ForwardCount > 1)
15074 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
15084 if(TDEntry.
HeadCode == OtherHeadCode)
15086 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15089 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15095 ReverseEntryPtr = &AVEntry;
15096 ReverseTDVectorNumber = x;
15099 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
15105 ReverseEntryPtr = &AVEntry;
15106 ReverseTDVectorNumber = x;
15113 if(ReverseCount == 0)
15115 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
15120 if(ReverseCount > 1)
15122 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
15129 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
15130 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
15131 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
15132 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
15136 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
15143 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
15148 if(SetDataAndCheckLocations)
15150 if(ForwardEntryPtr->LocationName ==
"")
15152 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15153 ". One or other service does not have a location set");
15160 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15161 ". One or other service does not have a location set");
15166 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
15168 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15169 " is at a different location to the referencing train " + MainHeadCode);
15178 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
15180 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15181 " has a different event time to the referencing train " + MainHeadCode);
15189 if(ForwardShuttleStart && ReverseShuttleFinish)
15194 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
15195 " first repeat restart time not consistent with finish service " + OtherHeadCode);
15201 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
15204 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15206 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
15207 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15213 if(ReverseEntryPtr->
Command ==
"Fjo")
15216 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15218 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
15219 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15225 if(ReverseEntryPtr->
Command ==
"Fns")
15228 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15230 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
15231 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15237 if(ForwardEntryPtr->Command ==
"Sfs")
15239 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
15242 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
15249 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
15251 if(ReverseEntryPtr->
Command !=
"Sfs")
15253 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
15261 if(SetDataAndCheckLocations)
15265 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
15272 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
15278 bool StationLocation =
false;
15281 if(TEIt->LocationName == ForwardEntryPtr->LocationName)
15285 StationLocation =
true;
15289 if(StationLocation)
15293 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15303 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15309 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15321 if(ForwardEntryPtr->Command ==
"Sns")
15323 if(ReverseEntryPtr->
Command !=
"Fns")
15325 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
15326 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
15332 if(ForwardEntryPtr->Command ==
"Fns")
15334 if(ReverseEntryPtr->
Command !=
"Sns")
15336 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
15337 " and forms a new service with headcode " + OtherHeadCode);
15344 if(SetDataAndCheckLocations)
15346 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15358 if(ForwardEntryPtr->Command ==
"jbo")
15360 if(ReverseEntryPtr->
Command !=
"Fjo")
15362 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
15363 " and is joined by a train with headcode " + OtherHeadCode);
15369 if(ForwardEntryPtr->Command ==
"Fjo")
15371 if(ReverseEntryPtr->
Command !=
"jbo")
15373 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
15374 " and joins a train with headcode " + OtherHeadCode);
15381 if(SetDataAndCheckLocations)
15383 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15399 if(ForwardShuttleStart)
15402 if(!ReverseShuttleFinish)
15405 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
15406 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
15412 if(ReverseShuttleStart)
15415 if(!ForwardShuttleFinish)
15418 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
15419 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
15426 if(SetDataAndCheckLocations)
15428 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15441 bool MainRepeat =
false, OtherRepeat =
false;
15451 OtherRepeat =
true;
15454 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
15456 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
15457 " and the associated train with headcode " + OtherHeadCode);
15462 if(MainRepeat && OtherRepeat)
15468 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
15469 " and the associated train with headcode " + OtherHeadCode);
15491 while(Input[1] ==
' ')
15493 if(Input.Length() > 1)
15495 Input = Input.SubString(2, Input.Length() - 1);
15509 while(Input[Input.Length()] ==
' ')
15511 if(Input.Length() > 1)
15513 Input = Input.SubString(1, Input.Length() - 1);
15523 AnsiString Output =
"";
15524 bool DelimiterFound =
false;
15526 for(
int x = 1; x < Input.Length() + 1; x++)
15530 if(Input[x] ==
' ')
15535 if((Input[x] !=
',') && (Input[x] !=
';'))
15537 DelimiterFound =
false;
15538 Output = Output + Input[x];
15542 DelimiterFound =
true;
15543 Output = Output + Input[x];
15555 DelimiterFound =
false;
15556 for(
int x = Input.Length(); x > 0; x--)
15560 if(Input[x] ==
' ')
15565 if((Input[x] !=
',') && (Input[x] !=
';'))
15567 DelimiterFound =
false;
15568 Output = AnsiString(Input[x]) + Output;
15572 DelimiterFound =
true;
15573 Output = AnsiString(Input[x]) + Output;
15598 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
15600 throw Exception(
"Error, first event not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
15612 LocationName = LocRear;
15616 LocationName = LocFront;
15618 if(LocationName ==
"")
15639 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
15680 int RearPosition = 0, FrontPosition = 0;
15683 if(RearPosition < 0)
15690 if(FrontPosition < 0)
15702 for(
int x = 0; x < 4; x++)
15704 if(RearTrackElement.
Conn[x] == FrontPosition)
15719 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
15726 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
15732 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
15763 AnsiString(RearExitPos));
15774 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
15776 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
15779 AnsiString RearName, FrontName;
15795 FrontName = FrontTrackElement.
ElementID;
15798 int LockedVectorNumber;
15918 if(((RearTrackElement.
Attribute == 1) && (RearExitPos == 1)) || ((RearTrackElement.
Attribute == 0) && (RearExitPos == 3)))
15923 StopTTClockMessage(157, HeadCode +
" can't be created, points set wrongly at " + RearName);
15931 if(((FrontTrackElement.
Attribute == 1) && (FrontEntryPos == 1)) || ((FrontTrackElement.
Attribute == 0) && (FrontEntryPos == 3)))
15936 StopTTClockMessage(158, HeadCode +
" can't be created, points set wrongly at " + RearName);
15970 "," + AnsiString(IncDigits));
15973 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
15978 return(BaseHeadCode);
15980 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
15981 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
15983 while(NextRepeatDigits >= 100)
15985 NextRepeatDigits -= 100;
15987 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
15989 if(NextRepeatDigitsStr.Length() < 2)
15991 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
15993 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
15996 return(NextRepeatHeadCode);
16004 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
16005 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
16007 return(NextRepeatTime);
16016 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
16017 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16018 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16019 int RepeatSecs = RepeatMinutes * 60;
16021 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
16055 NonRepeatingHeadCode);
16056 int ForwardCount = 0;
16057 int ReverseCount = 0;
16058 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
16068 if(TDEntry.
HeadCode == MainHeadCode)
16070 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16076 ForwardEntryPtr = &AVEntry;
16078 ForwardTDVectorNumber = x;
16083 if(ForwardCount == 0)
16086 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
16088 if(ForwardCount > 1)
16090 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
16100 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
16102 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16109 ReverseEntryPtr = &AVEntry;
16110 ReverseTDVectorNumber = x;
16116 if(ReverseCount == 0)
16118 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
16123 if(ReverseCount > 1)
16125 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
16126 NonRepeatingHeadCode);
16131 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
16133 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
16138 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
16140 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
16145 if(SetDataAndCheckLocations)
16147 if(ForwardEntryPtr->LocationName ==
"")
16149 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16150 ". One or other service does not have a location set");
16157 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16158 ". One or other service does not have a location set");
16163 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
16165 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
16166 " is at a different location to the referencing train " + MainHeadCode);
16172 if(ForwardEntryPtr->Command ==
"F-nshs")
16175 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
16177 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
16178 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
16184 if(ForwardEntryPtr->Command ==
"Fns-sh")
16188 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
16190 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
16191 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
16197 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
16200 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16202 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
16203 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
16221 if(ForwardEntryPtr->Command ==
"Sns-sh")
16223 if(ReverseEntryPtr->
Command !=
"F-nshs")
16225 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
16226 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
16232 if(ForwardEntryPtr->Command ==
"F-nshs")
16234 if(ReverseEntryPtr->
Command !=
"Sns-sh")
16236 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
16237 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
16244 if(SetDataAndCheckLocations)
16246 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16258 if(ForwardEntryPtr->Command ==
"Sns-fsh")
16260 if(ReverseEntryPtr->
Command !=
"Fns-sh")
16263 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
16264 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
16270 if(ForwardEntryPtr->Command ==
"Fns-sh")
16272 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
16275 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
16276 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
16283 if(SetDataAndCheckLocations)
16285 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
16309 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
16310 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16311 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16312 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
16314 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
16338 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
16341 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
16342 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16344 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16346 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16351 while(LastActionCommand ==
"Fns")
16353 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
16354 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16355 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16358 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
16359 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16366 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
16369 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
16370 ". The linking of two or more shuttles is not permitted.");
16390 ShowMessage(
ServiceReference +
" (not a valid service ref.): " + Message);
16408 ShowMessage(Message);
16417 int Mins = Input, Hrs = 0;
16423 AnsiString AnsiMins = AnsiString(Mins);
16424 if(AnsiMins.Length() == 1)
16426 AnsiMins =
"0" + AnsiMins;
16428 AnsiString AnsiHrs = AnsiString(Hrs);
16429 if(AnsiHrs.Length() == 1)
16431 AnsiHrs =
"0" + AnsiHrs;
16434 return(AnsiHrs +
':' + AnsiMins);
16474 AnsiString(ActionEventType) +
"," + LocationID);
16475 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
16480 Prefix =
" ERROR: ";
16483 Prefix =
" HELD: ";
16484 ErrorLog =
" can't enter railway, train obstructing entry position ";
16485 WarningStr =
" can't enter railway, train obstructing entry position ";
16490 Prefix =
" HELD: ";
16491 ErrorLog =
" can't enter railway, route set against it at entry position ";
16492 WarningStr =
" can't enter railway, route set against it at entry position ";
16497 Prefix =
" HELD: ";
16498 ErrorLog =
" can't be created, train obstructing ";
16499 WarningStr =
" can't be created, train obstructing ";
16504 Prefix =
" HELD: ";
16505 ErrorLog =
" can't be created on a locked route at ";
16506 WarningStr =
" can't be created on a locked route at ";
16511 Prefix =
" HELD: ";
16512 ErrorLog =
" can't enter on a locked route at ";
16513 WarningStr =
" can't enter on a locked route at ";
16518 Prefix =
" HELD: ";
16519 ErrorLog =
" can't be created, points set wrongly at ";
16520 WarningStr =
" can't be created, points set wrongly at ";
16525 ErrorLog =
" left railway unexpectedly at ";
16530 ErrorLog =
" left railway at an incorrect exit at ";
16535 ErrorLog =
" failed to split - location too short at ";
16536 WarningStr =
" failed to split, location too short at ";
16541 Prefix =
" HELD: ";
16542 ErrorLog =
" unable to split - other train obstructing at ";
16543 WarningStr =
" unable to split - other train obstructing at ";
16548 ErrorLog =
" stopped at buffers unexpectedly at position ";
16552 ErrorLog =
" failed to stop at ";
16557 ErrorLog =
" failed to split at ";
16562 ErrorLog =
" failed to be joined by other train at ";
16567 ErrorLog =
" failed to change its description at ";
16572 ErrorLog =
" failed to join other train at ";
16577 ErrorLog =
" failed to terminate at ";
16582 ErrorLog =
" failed to form new service at ";
16587 ErrorLog =
" failed to exit railway ";
16592 ErrorLog =
" failed to change direction at ";
16597 ErrorLog =
" failed to pass ";
16602 ErrorLog =
" facing buffers and unable to start at ";
16606 ErrorLog =
" DERAILED at position ";
16607 Prefix =
" DERAILMENT: ";
16612 ErrorLog =
" CRASHED INTO BUFFERS at ";
16613 Prefix =
" CRASH: ";
16618 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
16619 Prefix =
" CRASH: ";
16624 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
16625 Prefix =
" CRASH: ";
16629 else if(ActionEventType ==
FailSPAD)
16631 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
16632 Prefix =
" SPAD: ";
16637 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
16638 Prefix =
" SPAD RISK: ";
16643 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
16647 Prefix =
" WARNING: ";
16648 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
16649 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
16654 Prefix =
" WARNING: ";
16655 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
16656 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
16694 std::ofstream OutFile(
"TrainData.csv");
16698 ShowMessage(
"Output file TrainData.csv failed to open");
16705 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
16710 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
16711 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
16712 "RepeatNumber" <<
'\n' <<
'\n';
16713 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16716 AnsiString TimetableEntryTypeStr;
16722 TimetableEntryTypeStr =
"NoFormat";
16728 TimetableEntryTypeStr =
"TimeLoc";
16734 TimetableEntryTypeStr =
"TimeTimeLoc";
16740 TimetableEntryTypeStr =
"TimeCmd";
16746 TimetableEntryTypeStr =
"StartNew";
16752 TimetableEntryTypeStr =
"TimeCmdHeadCode";
16758 TimetableEntryTypeStr =
"FinRemHere";
16764 TimetableEntryTypeStr =
"FNSShuttle";
16770 TimetableEntryTypeStr =
"SNTShuttle";
16776 TimetableEntryTypeStr =
"SNSShuttle";
16782 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
16788 TimetableEntryTypeStr =
"FSHNewService";
16794 TimetableEntryTypeStr =
"Repeat";
16800 TimetableEntryTypeStr =
"Default";
16811 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
16812 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
16815 AnsiString RunningEntryStr;
16821 RunningEntryStr =
"NotStarted";
16827 RunningEntryStr =
"Running";
16833 RunningEntryStr =
"Exited";
16837 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
16854 ShowMessage(Message);
16855 BaseTime = TDateTime::CurrentDateTime();
16869 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
16882 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16884 for(
int x = 0; x < NumberOfTrains; x++)
16886 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16906 int NumberOfTrains;
16913 for(
int x = 0; x < NumberOfTrains; x++)
16950 for(
int x = 0; x < LockedRouteVectorSize; x++)
16957 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
16968 int LockedRouteVectorSize;
16975 for(
int x = 0; x < LockedRouteVectorSize; x++)
17033 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17041 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
17052 int ContinuationAutoSigVectorSize;
17059 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17129 if(AVFirstEntry.
Command ==
"Snt")
17153 CTEMMP.second = CTEEntry;
17160 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
17168 CTEMMP.second = CTEEntry;
17189 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17206 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
17208 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
17219 AnsiString RetStr =
"", PartStr =
"";
17334 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17338 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
17340 AnsiString ShortTTName =
"";
17342 for(
int x = TTFileName.Length(); x > 0; x--)
17344 if(TTFileName[x] ==
'\\')
17346 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
17351 ShowMessage(
"Creates two timetables named " + ShortTTName +
17352 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
17354 Screen->Cursor = TCursor(-11);
17356 AnsiString FormatNoDPStr =
"#######0";
17357 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
17360 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
17367 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
17369 if(TrainDataEntry.
Mass > 0)
17371 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
17375 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
17379 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
17383 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
17385 FirstHeadCode = TrainDataEntry.
HeadCode;
17386 int IncDigits = 0, IncMinutes = 0;
17388 if(!ActionVector.empty())
17390 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
17392 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
17393 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
17411 for(
unsigned int z = 0; z < ActionVector.size(); z++)
17416 AnsiString PartStr =
"", TimeStr =
"";
17433 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17437 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
17447 PartStr =
"Enters at " + LocName;
17460 PartStr =
"Created at " + LocName;
17474 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17479 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17485 else if(ActionVectorEntry.
Command ==
"Sfs")
17487 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
17491 else if(ActionVectorEntry.
Command ==
"Sns")
17493 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17501 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17507 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17515 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17518 AnsiString FirstHeadCode = TDE->
HeadCode;
17522 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
17534 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17536 OneTTEntry.
Action = PartStr;
17537 OneTTEntry.
Time = TimeStr;
17539 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17544 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
17550 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17555 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17563 else if(ActionVectorEntry.
Command ==
"jbo")
17565 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
17569 else if(ActionVectorEntry.
Command ==
"fsp")
17573 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17577 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17582 else if(ActionVectorEntry.
Command ==
"rsp")
17586 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17590 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17595 else if(ActionVectorEntry.
Command ==
"cdt")
17597 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
17600 else if(ActionVectorEntry.
Command ==
"dsc")
17602 PartStr =
"Changes description at " + ActionVectorEntry.
LocationName;
17608 if(ActionVectorEntry.
Command ==
"Fns")
17610 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17614 else if(ActionVectorEntry.
Command ==
"F-nshs")
17616 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17622 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
17629 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17635 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17642 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
17647 else if(ActionVectorEntry.
Command ==
"Frh")
17649 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
17654 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
17658 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
17668 else if(ActionVectorEntry.
Command ==
"Fer")
17670 AnsiString AllowedExits;
17674 else if(ActionVectorEntry.
Command ==
"Fjo")
17676 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
17685 OneTTEntry.
Action = PartStr;
17686 OneTTEntry.
Time = TimeStr;
17693 AllTTTrains->push_back(OneTTLine);
17697 std::ofstream TTFile(TTFileName.c_str());
17701 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
17702 delete AllTTTrains;
17737 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
17738 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17740 TTFile << AllTTTrains->at(x).Header.c_str();
17743 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17745 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17747 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
17751 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
17754 TTFile <<
'\n' <<
'\n';
17756 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
17758 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
17759 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17761 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17763 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
17767 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
17772 TTFile <<
'\n' <<
'\n';
17777 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17779 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
17781 std::ofstream TTFile2(TTFileName2.c_str());
17785 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
17786 delete AllTTTrains;
17790 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
17791 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
17792 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
17794 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
17799 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
17800 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17802 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17804 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
17806 bool GiveMessagesFalse =
false;
17807 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
17808 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
17809 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
17814 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
17815 TimeString = TimeString.SubString(9, 5);
17816 ActionString +=
" " + OtherHeadCode;
17818 if(TimeString.SubString(1, 7) ==
"End at ")
17821 TimeString = TimeString.SubString(8, 5);
17823 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
17824 AnsiMultiMapEntry.first = TimeString;
17825 AnsiMultiMapEntry.second = OneLine;
17826 TAMM->insert(AnsiMultiMapEntry);
17831 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
17833 TTFile2 << (AMMIT->second).c_str();
17835 delete AllTTTrains;
17844 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
17848 bool AnalysisError =
false;
17849 AnsiString SequenceLog =
"SequenceLog\n";
17892 TTrainDataVector::iterator TDVIt, TDVCopyIt;
17894 int IteratorNumber = 0;
17895 AnsiString AnsiSuffix =
"";
17902 if(TDVCopyIt->HeadCode == TDVIt->HeadCode)
17905 AnsiSuffix = AnsiString(Suffix);
17906 TDVCopyIt->ServiceReference = TDVIt->HeadCode +
"/" + AnsiSuffix;
17907 TDVCopyIt->HeadCode = TDVIt->HeadCode +
"/" + AnsiSuffix;
17913 int Increment = 0, SlashPos;
17915 AnsiString LinkedHeadCode;
17919 for(AVEIt = TDVCopyIt->ActionVector.begin(); AVEIt != TDVCopyIt->ActionVector.end(); AVEIt++)
17921 if(AVEIt->LinkedTrainEntryPtr != NULL)
17930 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
17932 if(LinkedHeadCode[x] ==
'/')
17934 SlashPos = LinkedHeadCode.Length() - x + 1;
17937 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
17938 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
17939 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
17945 AVEIt->OtherHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
17949 AVEIt->OtherHeadCode =
"";
17951 if(AVEIt->NonRepeatingShuttleLinkEntryPtr != NULL)
17953 Increment = AVEIt->NonRepeatingShuttleLinkEntryPtr - &
TrainDataVector.at(0);
17957 LinkedHeadCode = (*AVEIt->NonRepeatingShuttleLinkEntryPtr).
ServiceReference;
17960 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
17962 if(LinkedHeadCode[x] ==
'/')
17964 SlashPos = LinkedHeadCode.Length() - x + 1;
17967 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
17968 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
17969 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
17975 AVEIt->NonRepeatingShuttleLinkHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
17979 AVEIt->NonRepeatingShuttleLinkHeadCode =
"";
17984 SequenceLog +=
"1\n";
17987 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
17993 ServiceCallingLocsList.clear();
17994 if(ActionVector.empty())
17998 if(ActionVector.at(0).SignallerControl)
18002 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18020 int HLoc = TE.
HLoc;
18021 int VLoc = TE.
VLoc;
18022 AnsiString HString;
18023 AnsiString VString;
18026 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18030 HString = AnsiString(HLoc);
18034 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18038 VString = AnsiString(VLoc);
18040 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18063 else if(AVE.
Command ==
"cdt")
18076 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
18085 ServiceCallingLocsList.push_back(LName);
18089 int HLoc = TE.
HLoc;
18090 int VLoc = TE.
VLoc;
18091 AnsiString HString;
18092 AnsiString VString;
18095 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18099 HString = AnsiString(HLoc);
18103 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18107 VString = AnsiString(VLoc);
18109 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18113 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
18117 SequenceLog +=
"2\n";
18146 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
18152 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
18153 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
18154 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
18156 SequenceLog +=
"3\n";
18163 TDateTime LastTDTime;
18164 int IncMinutes = 0;
18166 if(ActionVector.empty())
18170 if(ActionVector.at(0).SignallerControl)
18174 if(AVLast->FormatType ==
Repeat)
18176 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18184 if(AVLast->ArrivalTime != TDateTime(-1))
18186 LastTDTime = AVLast->ArrivalTime;
18188 else if(AVLast->EventTime != TDateTime(-1))
18190 LastTDTime = AVLast->EventTime;
18209 SequenceLog +=
"4\n";
18246 int IncMinutes = 0;
18248 if(ActionVector.empty())
18252 if(ActionVector.at(0).SignallerControl)
18256 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
18258 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18260 for(
int y = 0; y < NumTrains; y++)
18274 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18289 LocServiceTimesVector.push_back(TLSTEntry);
18292 AnsiString IncTime =
"", FoundStopTime =
"";
18293 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18295 if(ActionVector.at(a).FormatType ==
TimeLoc)
18306 if(FoundStopTime ==
"")
18308 throw Exception(
"Failure to determine FoundStopTime for located Snt");
18310 int WhileCount = 0;
18319 if(IncTime >= FoundStopTime)
18323 LocServiceTimesVector.push_back(TLSTEntry);
18324 if(WhileCount > 2000)
18326 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
18339 int HLoc = TE.
HLoc;
18340 int VLoc = TE.
VLoc;
18341 AnsiString HString;
18342 AnsiString VString;
18345 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18349 HString = AnsiString(HLoc);
18353 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18357 VString = AnsiString(VLoc);
18359 TLSTEntry.
Location = HString +
'-' + VString;
18363 LocServiceTimesVector.push_back(TLSTEntry);
18371 LocServiceTimesVector.push_back(TLSTEntry);
18373 AnsiString IncTime =
"", FoundStopTime =
"";
18374 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18376 if(ActionVector.at(a).FormatType ==
TimeLoc)
18387 if(FoundStopTime ==
"")
18389 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18391 int WhileCount = 0;
18400 if(IncTime >= FoundStopTime)
18404 LocServiceTimesVector.push_back(TLSTEntry);
18405 if(WhileCount > 2000)
18407 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18417 bool SkipAddingMinutes =
false;
18420 LocServiceTimesVector.push_back(TLSTEntry);
18422 AnsiString IncTime =
"", FoundStopTime =
"";
18423 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18425 if(ActionVector.at(a).FormatType ==
TimeLoc)
18433 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr != NULL) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr != NULL)))
18437 LocServiceTimesVector.pop_back();
18438 SkipAddingMinutes =
true;
18443 if(FoundStopTime ==
"")
18445 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18447 if(!SkipAddingMinutes)
18449 int WhileCount = 0;
18458 if(IncTime >= FoundStopTime)
18462 LocServiceTimesVector.push_back(TLSTEntry);
18463 if(WhileCount > 2000)
18465 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18474 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
18476 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
18478 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
18479 LocServiceTimesVector.pop_back();
18480 LocServiceTimesVector.push_back(TLSTEntry);
18485 LocServiceTimesVector.push_back(TLSTEntry);
18491 LocServiceTimesVector.push_back(TLSTEntry);
18510 LocServiceTimesVector.push_back(TLSTEntry);
18514 AnsiString TempDepTime = TLSTEntry.
DepTime;
18516 LocServiceTimesVector.push_back(TLSTEntry);
18518 while(TLSTEntry.
AtLocTime < TempDepTime)
18523 TLSTEntry.
DepTime = TempDepTime;
18524 LocServiceTimesVector.push_back(TLSTEntry);
18528 LocServiceTimesVector.push_back(TLSTEntry);
18539 LocServiceTimesVector.push_back(TLSTEntry);
18542 LocServiceTimesVector.push_back(TLSTEntry);
18559 AnsiString HString;
18560 AnsiString VString;
18563 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18567 HString = AnsiString(HLoc);
18571 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18575 VString = AnsiString(VLoc);
18577 TLSTEntry.
Location = HString +
'-' + VString;
18579 LocServiceTimesVector.push_back(TLSTEntry);
18584 AnsiString FrhTime;
18585 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
18589 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
18597 LocServiceTimesVector.push_back(TLSTEntry);
18603 LocServiceTimesVector.push_back(TLSTEntry);
18608 else if(AVE.
Command ==
"Frh-sh")
18610 if(y == NumTrains - 1)
18616 LocServiceTimesVector.push_back(TLSTEntry);
18622 LocServiceTimesVector.push_back(TLSTEntry);
18635 SequenceLog +=
"5\n";
18668 TLocServiceTimesVector::iterator Ptr1, Ptr2;
18671 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18672 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
18674 std::ofstream TTFile3(TTFileName3.c_str());
18678 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
18682 if(LocServiceTimesVector.empty())
18684 ShowMessage(
"No timetabled services found");
18686 DeleteFile(TTFileName3);
18690 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
18691 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
18692 SequenceLog +=
"6\n";
18921 Ptr1 = LocServiceTimesVector.begin();
18923 while(Ptr2 != LocServiceTimesVector.end())
18925 while(Ptr2->Location == Ptr1->Location)
18928 if(Ptr2 == LocServiceTimesVector.end())
18935 if(Ptr2 != LocServiceTimesVector.end())
18943 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
18944 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
18945 MinuteString =
" minutes";
18946 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
18949 MinuteString =
" minute";
18951 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
18952 TTFile3 <<
",Platforms,Trains\n\n";
18954 Ptr1 = LocServiceTimesVector.begin();
18956 while(Ptr2 != LocServiceTimesVector.end())
18958 PreviousService =
"";
18959 NumTrainsAtLoc = 0;
18960 ServiceAndRepeatNumTotal =
"";
18962 NumPlatsAtThisLocCalculated =
false;
18964 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
18966 PreviousService =
"";
18967 NumTrainsAtLoc = 0;
18968 ServiceAndRepeatNumTotal =
"";
18970 NumPlatsAtThisLocCalculated =
false;
18974 if(Ptr2 == LocServiceTimesVector.end())
18979 if(Ptr2 == LocServiceTimesVector.end())
18983 while(Ptr2->Location == Ptr1->Location)
18985 PreviousService =
"";
18986 NumTrainsAtLoc = 0;
18987 ServiceAndRepeatNumTotal =
"";
18988 BasicTime = Ptr1->ArrTime;
18989 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
18993 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
18995 BasicTime = Ptr2->ArrTime;
18998 if(Ptr2 == LocServiceTimesVector.end())
19002 if(Ptr2->Location != Ptr1->Location)
19007 if(Ptr2 == LocServiceTimesVector.end())
19011 if(Ptr2->Location != Ptr1->Location)
19017 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
19021 if(!NumPlatsAtThisLocCalculated)
19024 NumPlatsAtThisLocCalculated =
true;
19026 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19028 if(ServiceAndRepeatNumTotal ==
"")
19030 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19031 NumTrainsAtLoc = 1;
19035 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19038 PreviousService = Ptr2->ServiceAndRepeatNum;
19039 if(ServiceAndRepeatNumTotal ==
"")
19041 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19042 NumTrainsAtLoc = 1;
19046 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19050 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
19052 int MaxNumberOfSameDirections = 0;
19053 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
19058 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19062 AnsiString Asterisk =
"";
19063 if(MaxNumberOfSameDirections >= NumPlats)
19068 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19069 ArrivalsPrinted =
true;
19070 ServiceAndRepeatNumTotal =
"";
19072 if(Ptr2 == LocServiceTimesVector.end())
19076 if(Ptr2->Location != Ptr1->Location)
19081 if(Ptr2 == LocServiceTimesVector.end())
19087 if(!ArrivalsPrinted)
19089 TTFile3 <<
"Nothing to report for arrivals";
19094 SequenceLog +=
"7\n";
19099 Ptr1 = LocServiceTimesVector.begin();
19101 while(Ptr2 != LocServiceTimesVector.end())
19103 while(Ptr2->Location == Ptr1->Location)
19106 if(Ptr2 == LocServiceTimesVector.end())
19113 if(Ptr2 != LocServiceTimesVector.end())
19120 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
19121 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
19122 MinuteString =
" minutes";
19123 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19126 MinuteString =
" minute";
19128 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
19129 TTFile3 <<
",Platforms,Trains\n\n";
19131 Ptr1 = LocServiceTimesVector.begin();
19133 while(Ptr2 != LocServiceTimesVector.end())
19135 PreviousService =
"";
19136 NumTrainsAtLoc = 0;
19137 ServiceAndRepeatNumTotal =
"";
19139 NumPlatsAtThisLocCalculated =
false;
19141 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19143 PreviousService =
"";
19144 NumTrainsAtLoc = 0;
19145 ServiceAndRepeatNumTotal =
"";
19147 NumPlatsAtThisLocCalculated =
false;
19151 if(Ptr2 == LocServiceTimesVector.end())
19156 if(Ptr2 == LocServiceTimesVector.end())
19160 while(Ptr2->Location == Ptr1->Location)
19162 PreviousService =
"";
19163 NumTrainsAtLoc = 0;
19164 ServiceAndRepeatNumTotal =
"";
19165 BasicTime = Ptr1->DepTime;
19166 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19170 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
19172 BasicTime = Ptr2->DepTime;
19175 if(Ptr2 == LocServiceTimesVector.end())
19179 if(Ptr2->Location != Ptr1->Location)
19184 if(Ptr2 == LocServiceTimesVector.end())
19188 if(Ptr2->Location != Ptr1->Location)
19194 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
19198 if(!NumPlatsAtThisLocCalculated)
19201 NumPlatsAtThisLocCalculated =
true;
19203 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19205 if(ServiceAndRepeatNumTotal ==
"")
19207 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19208 NumTrainsAtLoc = 1;
19212 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19215 PreviousService = Ptr2->ServiceAndRepeatNum;
19216 if(ServiceAndRepeatNumTotal ==
"")
19218 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19219 NumTrainsAtLoc = 1;
19223 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19227 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
19229 int MaxNumberOfSameDirections = 0;
19230 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
19235 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19239 AnsiString Asterisk =
"";
19240 if(MaxNumberOfSameDirections >= NumPlats)
19245 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19246 DeparturesPrinted =
true;
19247 ServiceAndRepeatNumTotal =
"";
19249 if(Ptr2 == LocServiceTimesVector.end())
19253 if(Ptr2->Location != Ptr1->Location)
19258 if(Ptr2 == LocServiceTimesVector.end())
19264 if(!DeparturesPrinted)
19266 TTFile3 <<
"Nothing to report for departures";
19271 SequenceLog +=
"8\n";
19278 Ptr1 = LocServiceTimesVector.begin();
19280 while(Ptr2 != LocServiceTimesVector.end())
19282 while(Ptr2->Location == Ptr1->Location)
19285 if(Ptr2 == LocServiceTimesVector.end())
19292 if(Ptr2 != LocServiceTimesVector.end())
19299 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
19300 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
19301 TTFile3 <<
",Platforms,Trains,\n\n";
19302 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19303 Ptr1 = LocServiceTimesVector.begin();
19305 while(Ptr2 != LocServiceTimesVector.end())
19307 PreviousService =
"";
19308 ServiceAndRepeatNumTotal =
"";
19309 NumTrainsAtLoc = 0;
19311 NumPlatsAtThisLocCalculated =
false;
19314 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19316 PreviousService =
"";
19317 ServiceAndRepeatNumTotal =
"";
19318 NumTrainsAtLoc = 0;
19320 NumPlatsAtThisLocCalculated =
false;
19324 if(Ptr2 == LocServiceTimesVector.end())
19329 if(Ptr2 == LocServiceTimesVector.end())
19333 while(Ptr2->Location == Ptr1->Location)
19335 if(Ptr1->FrhMarker ==
"Frh")
19338 Ptr1->FrhMarker =
"FrhCounted";
19340 PreviousService =
"";
19341 NumTrainsAtLoc = 0;
19342 ServiceAndRepeatNumTotal =
"";
19343 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19347 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
19350 if(Ptr1->FrhMarker ==
"Frh")
19353 Ptr1->FrhMarker =
"FrhCounted";
19356 if(Ptr2 == LocServiceTimesVector.end())
19360 if(Ptr2->Location != Ptr1->Location)
19365 if(Ptr2 == LocServiceTimesVector.end())
19369 if(Ptr2->Location != Ptr1->Location)
19373 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
19375 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
19379 if(!NumPlatsAtThisLocCalculated)
19382 NumPlatsAtThisLocCalculated =
true;
19384 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19386 if(ServiceAndRepeatNumTotal ==
"")
19388 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
19389 NumTrainsAtLoc = 1;
19393 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
19396 PreviousService = Ptr2->ServiceAndRepeatNum;
19397 if(ServiceAndRepeatNumTotal ==
"")
19399 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
19400 NumTrainsAtLoc = 1;
19404 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
19407 if(Ptr1->FrhMarker ==
"Frh")
19410 Ptr1->FrhMarker =
"FrhCounted";
19413 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
19417 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
19419 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
19421 AnsiString Asterisk =
"";
19422 if(NumTrainsAtLoc > NumPlats)
19429 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19431 else if(FrhCount == 1)
19433 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19437 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19439 LastFrhCount = FrhCount;
19440 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
19441 AtLocsPrinted =
true;
19442 ServiceAndRepeatNumTotal =
"";
19445 if(Ptr2 == LocServiceTimesVector.end())
19449 if(Ptr2->Location != Ptr1->Location)
19454 if(Ptr2 == LocServiceTimesVector.end())
19462 TTFile3 <<
"Nothing to report for trains at locations";
19467 SequenceLog +=
"9\n";
19501 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
19506 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
19515 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19517 SingleServiceEntry = TDE;
19519 for(
unsigned int y = 0; y < SSAV.size(); y++)
19521 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
19523 SingleServiceVector.push_back(SingleServiceEntry);
19526 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
19528 PartServiceEntry = TDE;
19530 for(
unsigned int z = 0; z <= y; z++)
19535 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
19536 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
19539 PartServiceVector.push_back(PartServiceEntry);
19540 if(SSAV.at(y).Command ==
"fsp")
19542 SSAV.at(y).Command =
"Front split - original service continues below";
19543 SSAV.at(y).OtherHeadCode =
"";
19545 if(SSAV.at(y).Command ==
"rsp")
19547 SSAV.at(y).Command =
"Rear split - original service continues below";
19548 SSAV.at(y).OtherHeadCode =
"";
19552 else if(SSAV.at(y).Command ==
"Fns")
19554 SSAV.at(y).Command =
"chr-Fns";
19555 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19556 PartServiceVector.push_back(SingleServiceEntry);
19559 else if(SSAV.at(y).Command ==
"Fns-sh")
19561 SSAV.at(y).Command =
"chr-Fns-sh";
19562 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19563 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19564 PartServiceVector.push_back(SingleServiceEntry);
19567 else if(SSAV.at(y).Command ==
"F-nshs")
19569 SSAV.at(y).Command =
"chr-F-nshs";
19570 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19571 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19572 PartServiceVector.push_back(SingleServiceEntry);
19578 SequenceLog +=
"10\n";
19582 AnsiString NextRef;
19583 while(!PartServiceVector.empty())
19585 PartServiceEntry = PartServiceVector.at(0);
19586 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
19588 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
19590 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
19594 bool FinishType =
true, FoundFlag =
false;
19601 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
19605 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19609 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19615 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19616 SingleServiceVector.push_back(PartServiceVector.at(0));
19617 PartServiceVector.erase(PartServiceVector.begin());
19622 NewPartServiceEntry = PartServiceVector.at(0);
19626 PartServiceVector.push_back(NewPartServiceEntry);
19629 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
19634 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
19637 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19639 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
19642 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19644 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19647 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
19650 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19651 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19652 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19653 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19656 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
19660 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19661 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19662 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19670 SequenceLog += +
"11\n";
19671 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
19675 if(!PartServiceVector.empty())
19677 SequenceLog +=
"12\n";
19678 throw Exception(
"PartServiceVector should be empty here - size = " + AnsiString(PartServiceVector.size()));
19680 SequenceLog +=
"13\n";
19727 bool BufferFacingUnReportedFlag =
true;
19728 bool TrainFacingBuffersReported =
false;
19729 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19735 SequenceLog +=
"13a\n";
19736 throw Exception(
"Repeat entry present in SingleServiceVector at position " + AnsiString(x));
19739 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19741 bool BufferFlag =
false;
19742 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
19743 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
19744 AnsiString FrontLocName = AV.at(0).LocationName;
19745 int NextEntryPos, NextExitPos;
19748 if(ThisElement.
Conn[0] == RearTVPos)
19752 else if(ThisElement.
Conn[1] == RearTVPos)
19756 else if(ThisElement.
Conn[2] == RearTVPos)
19760 else if(ThisElement.
Conn[3] == RearTVPos)
19772 if(ThisElement.
Conn[ThisExitPos] == -1)
19774 SequenceLog =
"13b\n";
19775 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
19778 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
19779 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
19781 BufferFlag =
false;
19786 BufferFlag =
false;
19791 BufferFlag =
false;
19799 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
19801 ThisElement = NextElement;
19807 if(NextEntryPos == 0)
19811 else if(NextEntryPos == 1)
19815 else if(NextEntryPos == 2)
19819 else if(NextEntryPos == 3)
19824 ThisElement = NextElement;
19825 ThisExitPos = NextExitPos;
19830 if(BufferFacingUnReportedFlag)
19832 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
19833 BufferFacingUnReportedFlag =
false;
19835 if(AV.at(1).Command !=
"cdt")
19837 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation with no immediate change of direction\n";
19838 TrainFacingBuffersReported =
true;
19843 if(!TrainFacingBuffersReported)
19845 TTFile3 <<
"Nothing to report for train facing directions\n\n";
19851 SequenceLog +=
"13c\n";
19854 AnsiString LocationNameToBeChecked =
"";
19855 bool MissingcdtUnreportedFlag =
true;
19857 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19860 unsigned int y = 0;
19861 int FirstInstance = 9999, SecondInstance = 9999;
19862 bool FullBreak =
false;
19863 MarkerList.clear();
19865 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
19874 LocationNameToBeChecked =
"";
19880 if(LocationNameToBeChecked ==
"")
19887 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
19890 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
19895 (AVEntry.
Command ==
"Frh-sh"))
19910 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
19912 AnsiString LocationName;
19919 int ExitLoc = TDEntry.
ActionVector.at(a).ExitList.front();
19924 LocationName = TDEntry.
ActionVector.at(a).LocationName;
19926 if(LocationName == LocationNameToBeChecked)
19928 SecondInstance = a;
19930 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
19932 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
19934 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
19937 if(MissingcdtUnreportedFlag)
19939 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
19941 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
19942 MarkerList.push_back(FirstInstance);
19943 MarkerList.push_back(SecondInstance);
19945 MissingcdtUnreportedFlag =
false;
19956 if(MissingcdtUnreportedFlag)
19958 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
19964 SequenceLog +=
"14\n";
19973 typedef std::list<AnsiString> TLocList;
19974 TLocList BackwardList, ForwardList;
19975 bool IntroLineNeeded =
true;
19976 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19978 unsigned int cdtPosition = 9999;
19979 AnsiString cdtLocation =
"";
19980 bool FoundSameName =
false;
19981 bool FerEntry =
false;
19982 MarkerList.clear();
19984 for(
unsigned int y = 0; y <= TDEntry.
ActionVector.size(); y++)
19991 BackwardList.clear();
19992 ForwardList.clear();
19993 bool ValidEnd =
false;
19999 (AVEntry.
Command ==
"Frh-sh"))
20004 if(FerEntry || ValidEnd)
20006 if(MarkerList.empty())
20013 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
20015 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
20017 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
20021 if(IntroLineNeeded)
20023 TTFile3 <<
"Questionable change of direction analysis.\n\n";
20024 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above (up to the start or another direction change)\n";
20025 TTFile3 <<
"and below (down to the end or another direction change) but not counting the change of direction location itself.\n\n";
20026 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
20027 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
20028 IntroLineNeeded =
false;
20030 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
20045 for(
int z = y - 1; z >= 0; z--)
20048 if(AVEntry2.
Command ==
"cdt")
20052 AnsiString LocName =
"";
20062 if((LocName !=
"") && (AVEntry2.
LocationName != cdtLocation))
20064 BackwardList.push_back(LocName);
20067 BackwardList.sort();
20068 BackwardList.unique();
20069 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
20078 AnsiString LocName =
"";
20079 if(AVEntry3.
Command ==
"Fer")
20081 int ExitLoc = AVEntry3.
ExitList.front();
20089 if((LocName !=
"") && (AVEntry3.
LocationName != cdtLocation))
20091 ForwardList.push_back(LocName);
20094 ForwardList.sort();
20095 ForwardList.unique();
20096 FoundSameName =
false;
20098 if(!BackwardList.empty() && !ForwardList.empty())
20100 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
20102 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
20106 FoundSameName =
true;
20113 MarkerList.push_back(cdtPosition);
20118 if(IntroLineNeeded)
20120 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
20138 SequenceLog +=
"15\n";
20144 catch(
const Exception &e)
20146 AnsiString TTErrorFileName =
"Analysis Error.txt";
20147 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
20148 std::ofstream TTError(TTErrorFileName.c_str());
20151 ShowMessage(
"Analysis error file failed to open - can't be created");
20155 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
20156 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
20157 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
20160 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
20170 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
20172 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
20174 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
20176 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
20177 AnsiString Marker =
"";
20178 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
20181 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
20183 if(
int(x) == *MLIt)
20213 if(AVE.
Command.SubString(1,3) ==
"chr")
20222 AVE.
Command =
"Change of service to ";
20224 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
20226 AVE.
Command =
"Change to shuttle finishing service";
20228 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
20255 AnsiString ListOfExits =
"";
20264 VecFile << Marker <<
"Frh" <<
'\n';
20279 for(
unsigned int x = 0; x < Vector.size(); x++)
20282 if(Vector.at(x).ServiceReference == HeadCode)
20284 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
20286 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
20289 FinishType =
false;
20294 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
20297 FinishType =
false;
20302 return(Vector.at(x));
20306 return(Vector.at(Vector.size() - 1));
20315 if((Time1 ==
"") || (Time2 ==
""))
20320 int Mins = Time1.SubString(4,2).ToInt();
20321 int Hours = Time1.SubString(1,2).ToInt();
20322 int Time1Mins = (Hours * 60) + Mins;
20323 Mins = Time2.SubString(4,2).ToInt();
20324 Hours = Time2.SubString(1,2).ToInt();
20325 int Time2Mins = (Hours * 60) + Mins;
20326 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
20338 bool &AnalysisError,
int &MaxNumberOfSameDirections)
20345 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
20347 std::list<AnsiString> ServiceList;
20349 bool EvenComma =
false;
20350 for(
int x = 1; x <= Input.Length(); x++)
20352 TempStr1 = Input[x];
20353 if(TempStr1 == AnsiString(
',') && EvenComma)
20359 TempStr2 += Input[x];
20361 if(TempStr1 == AnsiString(
','))
20363 EvenComma = !EvenComma;
20367 while(TempStr2.Length() > 0)
20369 SCPos = TempStr2.Pos(
';');
20372 OneService = TempStr2.SubString(1, SCPos - 1);
20373 ServiceList.push_back(OneService);
20374 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
20378 ServiceList.push_back(TempStr2);
20382 ServiceList.sort();
20383 ServiceList.unique();
20384 NumTrainsAtLoc = ServiceList.size();
20387 int DirectionMarker = 0;
20389 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
20391 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20393 *SLIt = *SLIt +
"&0";
20395 SLIt3 = ServiceList.end();
20397 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
20398 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
20399 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
20401 MaxNumberOfSameDirections = 0;
20402 int SameDirectionCount = 0;
20404 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
20408 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
20414 CommaPos1 = SLIt1->Pos(
',');
20415 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
20417 SpacePos = ServiceRef1.Pos(
' ');
20421 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
20422 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
20423 if(RepeatInfo1[1] ==
'F')
20429 SpacePos = RepeatInfo1.Pos(
' ');
20430 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
20433 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
20435 AmpersandPos = AnsiTime1.Pos(
'&');
20436 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
20441 throw Exception(
"ASCLIt1 Error in " + Input);
20443 ServiceCallingLocsList1 = ASCLIt1->second;
20444 AmpersandPos = SLIt1->Pos(
'&');
20445 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
20446 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
20448 SameDirectionCount = 1;
20449 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
20451 CommaPos2 = SLIt2->Pos(
',');
20452 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
20454 SpacePos = ServiceRef2.Pos(
' ');
20458 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
20459 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
20460 if(RepeatInfo2[1] ==
'F')
20466 SpacePos = RepeatInfo2.Pos(
' ');
20467 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
20470 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
20472 AmpersandPos = AnsiTime2.Pos(
'&');
20473 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
20478 throw Exception(
"ASCLIt2 Error in " + Input);
20480 ServiceCallingLocsList2 = ASCLIt2->second;
20482 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
20484 int AmpersandPos = SLIt2->Pos(
'&');
20485 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
20486 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
20487 SameDirectionCount++;
20490 if(SameDirectionCount > MaxNumberOfSameDirections)
20492 MaxNumberOfSameDirections = SameDirectionCount;
20497 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
20500 AmpersandPos = SLIt3->Pos(
'&');
20501 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
20502 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
20505 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20508 AmpersandPos = SLIt->Pos(
'&');
20509 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
20510 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
20511 DirectionMarker = DirectionMarkerString.ToInt();
20512 AnsiString DirectionSuffix =
"";
20514 if(DirectionMarker < 27)
20516 c = 64 + DirectionMarker;
20517 DirectionSuffix =
"," + AnsiString(c);
20519 else if(DirectionMarker < 53)
20521 c = 65 + DirectionMarker - 27;
20522 DirectionSuffix =
",A" + AnsiString(c);
20526 DirectionSuffix =
",?";
20528 *SLIt = ServiceWithoutMarker + DirectionSuffix;
20531 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20533 Output = Output + *SLIt +
",";
20535 if(Output.Length() > 0)
20537 Output = Output.SubString(1, Output.Length() - 1);
20543 catch(
const Exception &e)
20545 AnalysisError =
true;
20557 AnsiString InternalInput = Input, Output =
"", OneService =
"";
20559 std::list<AnsiString> ServiceList;
20561 while(InternalInput.Length() > 0)
20563 CommaPos = InternalInput.Pos(
',');
20566 OneService = InternalInput.SubString(1, CommaPos - 1);
20567 ServiceList.push_back(OneService);
20568 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
20572 ServiceList.push_back(InternalInput);
20573 InternalInput =
"";
20577 ServiceList.sort();
20578 ServiceList.unique();
20579 NumTrainsAtLoc = ServiceList.size();
20580 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20582 Output = Output + *SLIt +
",";
20584 if(Output.Length() > 0)
20586 Output = Output.SubString(1, Output.Length() - 1);
20599 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
20601 std::list<AnsiString>::iterator LP1, LP2, ListPtr1, ListPtr2, LocPtr1, LocPtr2;
20606 bool LocFound =
false;
20607 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
20609 TDateTime FirstServiceTime;
20612 int Ref1Target = 0, Ref1Count = 0;
20613 int Ref2Target = 0, Ref2Count = 0;
20631 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
20634 if((*ListPtr1) == Location)
20636 LocPtr1 = ListPtr1;
20639 if(ListPtr1->SubString(1, 3) ==
"%%%")
20641 AnsiString CDTTime = ListPtr1->SubString(4, 5);
20646 FirstServiceTime = TDateTime(-1);
20647 bool BreakFlag =
false;
20650 if(TDVIt->ServiceReference == Ref1)
20652 if(Ref1Target > Ref1Count)
20657 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20658 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20662 FirstServiceTime = AVIt->EventTime;
20668 FirstServiceTime = AVIt->ArrivalTime;
20674 FirstServiceTime = AVIt->DepartureTime;
20685 if(IncMinutes == -1)
20687 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20689 if(FirstServiceTime == TDateTime(-1))
20691 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20695 if(!Arrival && (Time1 == CDTTime))
20700 if(Arrival && (Time1 == CDTTime))
20704 if(Time1 > CDTTime)
20709 if(Time1 < CDTTime)
20722 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
20724 if((*ListPtr2) == Location)
20726 LocPtr2 = ListPtr2;
20729 if(ListPtr2->SubString(1, 3) ==
"%%%")
20731 AnsiString CDTTime = ListPtr2->SubString(4, 5);
20736 FirstServiceTime = TDateTime(-1);
20737 bool BreakFlag =
false;
20740 if(TDVIt->ServiceReference == Ref2)
20742 if(Ref2Target > Ref2Count)
20747 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20748 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20752 FirstServiceTime = AVIt->EventTime;
20758 FirstServiceTime = AVIt->ArrivalTime;
20764 FirstServiceTime = AVIt->DepartureTime;
20775 if(IncMinutes == -1)
20777 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20779 if(FirstServiceTime == TDateTime(-1))
20781 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20785 if(!Arrival && (Time2 == CDTTime))
20790 if(Arrival && (Time2 == CDTTime))
20794 if(Time2 > CDTTime)
20799 if(Time2 < CDTTime)
20814 LP1 = List1.begin();
20816 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
20818 if(ListPtr1 == List1.begin())
20822 if(ListPtr1->SubString(1, 3) ==
"%%%")
20829 LP2 = List2.begin();
20831 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
20833 if(ListPtr2 == List2.begin())
20837 if(ListPtr2->SubString(1, 3) ==
"%%%")
20847 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20849 if(ListPtr1 == LocPtr1)
20853 if(ListPtr1->SubString(1, 3) ==
"%%%")
20857 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20859 if(ListPtr2 == LocPtr2)
20863 if(ListPtr2->SubString(1, 3) ==
"%%%")
20867 if((*ListPtr1) == (*ListPtr2))
20884 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20886 if(ListPtr1 == List1.end())
20890 if(ListPtr1->SubString(1, 3) ==
"%%%")
20894 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20896 if(ListPtr2 == List2.end())
20900 if(ListPtr2->SubString(1, 3) ==
"%%%")
20904 if((*ListPtr1) == (*ListPtr2))
20921 if(ExitList.empty())
20927 AnsiString ExitLocList =
"";
20930 unsigned int Counter = 0;
20931 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
20935 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
20937 ExitLocList +=
"\n";
20940 if(StartName ==
"")
20942 if(ExitList.size() == 1)
20946 return(
" at " + ID);
20951 if(ExitList.size() < 4)
20953 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
20958 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
20963 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
20968 if(ExitList.size() < 4)
20970 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
20975 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
20981 if(ExitList.size() < 4)
20983 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
20984 return(
" at " + StartName);
20988 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
20989 return(
" at " + StartName);
21029 AnsiString FormatStr =
"####0.0";
21030 AnsiString AvLateArrMins =
"";
21031 AnsiString AvEarlyArrMins =
"";
21032 AnsiString AvLatePassMins =
"";
21033 AnsiString AvEarlyPassMins =
"";
21034 AnsiString AvLateDepMins =
"";
21035 AnsiString AvLateExitMins =
"";
21036 AnsiString AvEarlyExitMins =
"";
21039 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21072 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
21073 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
21085 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21089 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21097 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21101 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21109 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
21117 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21121 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21125 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
21129 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21133 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21137 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
21142 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
21146 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
21150 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21154 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21158 PerfFile <<
LateExits <<
" late exits" <<
'\n';
21162 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21166 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21170 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
21175 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
21179 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
21183 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21187 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21191 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
21193 TDateTime TempExcessLCDownTime;
21207 if(TempExcessLCDownTime > TDateTime(0))
21213 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
21217 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
21229 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
21233 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
21269 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
21273 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
21279 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
21283 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
21286 AnsiString AvLateMinsLocsNotReached =
"";
21292 if(LocsNotReached > 0)
21295 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
21299 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
21303 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
21315 PerfFile <<
Derailments <<
" derailments" <<
'\n';
21319 PerfFile <<
Derailments <<
" derailment" <<
'\n';
21329 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
21331 bool DerailSPADFlag =
false, CrashFlag =
false;
21333 int OverallScorePercent = 100;
21334 int TotArrDepExit = 0;
21335 double TotLateMinsFactor = 1;
21336 double MissedStopAndSPADRiskFactor = 1;
21337 double NetNegFactor = 1;
21347 OverallScorePercent = 5;
21348 DerailSPADFlag =
true;
21352 OverallScorePercent = 0;
21355 if(OverallScorePercent == 100)
21360 LatenessPenalty = 0;
21366 if(TotArrDepExit > 0)
21375 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
21377 OverallScorePercent = 100 * NetNegFactor;
21380 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
21383 AnsiString OneFailureString =
", though the failure would account for some poor performance";
21384 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
21385 AnsiString AddedString =
"";
21388 AddedString = OneFailureString;
21392 AddedString = TwoOrMoreFailureString;
21394 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
21395 AnsiString Rating =
"";
21396 if(OverallScorePercent == 100)
21398 Rating =
"Perfect!";
21400 else if(OverallScorePercent >= 95)
21402 Rating =
"Excellent";
21404 else if(OverallScorePercent >= 90)
21406 Rating =
"Very good";
21408 else if(OverallScorePercent >= 80)
21412 else if(OverallScorePercent >= 70)
21416 else if(OverallScorePercent >= 60)
21418 Rating =
"Unacceptable" + AddedString;
21420 else if(OverallScorePercent >= 50)
21422 Rating =
"Poor" + AddedString;
21424 else if(OverallScorePercent >= 40)
21426 Rating =
"Bad" + AddedString;
21428 else if(OverallScorePercent >= 30)
21430 Rating =
"Very bad" + AddedString;
21432 else if(OverallScorePercent >= 20)
21434 Rating =
"Terrible" + AddedString;
21436 else if(OverallScorePercent >= 10)
21438 Rating =
"Appalling" + AddedString;
21440 else if(OverallScorePercent >= 5)
21444 Rating =
"Disastrous - potential loss of life";
21449 Rating =
"Dire" + AddedString;
21452 else if(OverallScorePercent < 5)
21456 Rating =
"Catastrophic - loss of life";
21460 Rating =
"Abysmal";
21463 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
21467 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
21469 PerfFile <<
'\n' <<
"***************************************";
21479 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21529 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21564 int IncrementalMinutes = 0;
21578 bool TrainOperatingFlag =
false;
21583 TrainOperatingFlag =
true;
21587 if(TrainOperatingFlag)
21595 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
21642 AnsiString HeadCode;
21646 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21650 HCandTrainPosParam.first = HeadCode;
21651 HCandTrainPosParam.second = TrainID;
21653 if((TimeToAct >= 0) && (TimeToAct < 59.9))
21656 OpTimeToActMultiMapEntry.first = TimeToAct;
21657 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21686 float TimeToAct = 0;
21687 int DistanceToRedSignal = 0;
21690 ContinuationEntryVecPosVector.clear();
21691 bool LaterTrain =
false;
21695 LaterTrain =
false;
21696 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
21707 if(!ContinuationEntryVecPosVector.empty())
21709 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
21711 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
21725 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
21726 AnsiString HeadCode = CTEIt->second.HeadCode;
21727 float CurrentStopTime;
21728 float LaterStopTime;
21729 float RecoverableTime;
21732 int DistanceToExit;
21734 bool SigControlAndCanPassRedSignal =
false;
21742 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
21748 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
21749 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
21752 if(AvTrackSpeed < 30)
21756 if(DistanceToRedSignal == -1)
21762 int Speed = AvTrackSpeed;
21763 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
21764 if(AvTrackSpeed > MaxSpeed)
21768 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
21771 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
21774 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
21779 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
21780 TimeToAct += MinsBefEnter;
21783 HCandTrainPosParam.first = HeadCode;
21784 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
21787 if(TimeToAct < 59.9)
21789 OpTimeToActMultiMapEntry.first = TimeToAct;
21790 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21815 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21825 TimeToExitMultiMapEntry.first = ExitPair;
21826 TimeToExitMultiMapEntry.second = ExitInfo;
21836 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
21837 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
21846 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
21847 int DistanceToRedSignal = 0;
21848 DistanceToExit = -1;
21849 ExitPair.first = -1;
21850 ExitPair.second = -1;
21851 int CumTrackSpeed = 0;
21853 int TrackSpeedCount = 0;
21854 float KmPerLocationStop;
21855 float MaxAllowableSpeed;
21865 int CurrentElement = TrackVectorPosition;
21866 int CurrentEntryPos = TrackVectorPositionEntryPos;
21871 CurrentStopTime = 0;
21873 RecoverableTime = 0;
21874 if(CurrentElement == -1)
21879 int CurrentExitPos;
21884 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
21888 CurrentExitPos = 1;
21892 CurrentExitPos = 3;
21897 CurrentExitPos = 0;
21936 TimeToDepart+= 0.5;
21938 if(TimeToDepart < 0.5)
21940 TimeToDepart = 0.5;
21943 CurrentStopTime = float(TimeToDepart);
21951 CurrentStopTime = float(TimeToDepart);
21962 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
21973 else if(SigControlAndCanPassRedSignal)
21978 if((NextEntryPos == 0) || (NextEntryPos == 2))
21999 CurrentElement = NextElement;
22000 CurrentEntryPos = NextEntryPos;
22001 CurrentExitPos = NextExitPos;
22013 int LaterStopNumber = 0;
22017 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
22026 if(CurrentEntryPos > 1)
22041 DistanceToExit = DistanceToRedSignal;
22046 if(TrackSpeedCount > 0)
22048 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22052 if(CurrentEntryPos > 1)
22063 if(LaterStopNumber > 0)
22065 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22066 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22072 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22076 if(AvTrackSpeed > MaxAllowableSpeed)
22078 AvTrackSpeed = MaxAllowableSpeed;
22090 bool StopRequired =
false;
22109 int TrainOnElement;
22116 if(CurrentEntryPos > 1)
22125 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
22134 double StopTimeDouble;
22147 if(StopTimeDouble < 0.5)
22149 StopTimeDouble = 0.5;
22153 LaterStopTime += float(StopTimeDouble);
22154 RecoverableTime += StopTimeDouble - 0.5;
22155 if((LaterStopNumber == 1) && (TrainID > -1))
22163 if((AVPtr + 1)->FormatType ==
TimeLoc)
22167 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22178 if(StopTimeDouble < 0.5)
22180 StopTimeDouble = 0.5;
22183 LaterStopTime += float(StopTimeDouble);
22184 RecoverableTime += StopTimeDouble - 0.5;
22185 if((LaterStopNumber == 1) && (TrainID > -1))
22195 StopTimeDouble = double((AVPtr + 2)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22206 if(StopTimeDouble < 0.5)
22208 StopTimeDouble = 0.5;
22211 LaterStopTime += float(StopTimeDouble);
22212 RecoverableTime += StopTimeDouble - 0.5;
22213 if((LaterStopNumber == 1) && (TrainID > -1))
22230 if(NextElement == -1)
22239 if((NextEntryPos == 0) || (NextEntryPos == 2))
22260 CurrentElement = NextElement;
22261 CurrentEntryPos = NextEntryPos;
22262 CurrentExitPos = NextExitPos;
22267 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22280 if(TrackSpeedCount > 0)
22282 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22286 if(CurrentEntryPos > 1)
22297 if(LaterStopNumber > 0)
22299 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22300 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22306 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22310 if(AvTrackSpeed > MaxAllowableSpeed)
22312 AvTrackSpeed = MaxAllowableSpeed;
22315 return(DistanceToRedSignal);